Saltar al contenido
webtype.orgwebtype.org

    ↑↓ mover · ⏎ abrir · esc cerrar

    N.º 253 · 5 de septiembre de 2026 · Difícil

    Snake case

    Implementa SnakeCase<S> para que "helloWorld" se convierta en "hello_world". Solo las letras cuentan como mayúsculas — los dígitos y símbolos deben pasar intactos.

    01

    Intenta el puzle tú mismo

    Par 4

    Puzle

    snake-case.ts
    Intento 1 de 4Aún sin comprobar

    Sustituye ??? — tu solución se comprueba con los casos de abajo. Tab indenta; pulsa Escape y luego Tab para sacar el foco.

    Comprobaciones

    4
    • SnakeCase<'helloWorld'>—
      → 'hello_world'
    • SnakeCase<'a1B'>—
      → 'a1_b'
    • SnakeCase<'foo'>—
      → 'foo'
    • SnakeCase<''>—
      → ''

    Cómo se juzga una comprobación Igualdad exacta de tipos, no asignabilidad — una intersección no es lo mismo que el objeto aplanado.

    Cómo le fue a todo el mundo

    Menos de 5 personas han resuelto este puzle hasta ahora. La distribución aparece cuando la muestra sea lo bastante grande como para significar algo.

    Juego corto

    Menos caracteres

    Aún no hay marcas públicas.

    Archivo
    02

    Solución comentada

    Publicado el 6 de septiembre de 2026

    La solución

    type SnakeCase<S extends string> =
      S extends `${infer H}${infer R}`
        ? H extends Uppercase<H>
          ? H extends Lowercase<H>
            ? `${H}${SnakeCase<R>}`
            : `_${Lowercase<H>}${SnakeCase<R>}`
          : `${H}${SnakeCase<R>}`
        : S

    El error más común

    type SnakeCase<S extends string> =
      S extends `${infer H}${infer R}`
        ? H extends Uppercase<H>
          ? `_${Lowercase<H>}${SnakeCase<R>}`
          : `${H}${SnakeCase<R>}`
        : S

    "1" extends Uppercase<"1"> es cierto, porque Uppercase deja todo lo que no sea una letra minúscula exactamente como lo encontró. Así que cada dígito, espacio y símbolo se trata como mayúscula y recibe su propio guion bajo: "a1B" sale como "a_1_b". Ser mayúscula no es una prueba sino dos — igual a tu forma en mayúsculas *y* distinto de tu forma en minúsculas.

    Línea por línea

    1. `${infer H}${infer R}`

      Dos marcadores sin nada entre ellos separan exactamente un carácter. Es el equivalente a nivel de tipos de recorrer una cadena índice a índice.

    2. H extends Lowercase<H> ? ... : ...

      La segunda prueba es la que excluye a los no-letras. Un dígito es igual tanto a su forma mayúscula como a la minúscula, así que cae en la rama que lo deja pasar sin cambios.

    3. : S

      La cadena vacía no coincide con ningún patrón de un carácter, así que cae al caso base y se devuelve a sí misma — que es también lo que detiene la recursión.

    Para recordar

    Uppercase y Lowercase son funciones totales: nunca fallan, simplemente no hacen nada a los caracteres sin caja. Cualquier prueba basada en una sola de ellas clasificará mal, y en silencio, cada dígito y símbolo que encuentres.

    Usa