Saltar al contenido
webtype.orgwebtype.org#214 route-params · par 3

    ↑↓ mover · ⏎ abrir · esc cerrar

    N.º 214 · 22 de julio de 2026 · Media

    Parámetros de ruta

    Implementa `ExtractParams<Path>` para que cada segmento `:param` de una ruta se convierta en clave de un tipo objeto, con valor `string`. El resultado debe ser un único objeto plano — una intersección no pasará.

    01

    Intenta el puzle tú mismo

    Par 3

    Puzle

    route-params.ts
    type Prettify<T> = { [K in keyof T]: T[K] } & {}
    Intento 1 de 3Aú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
    • ExtractParams<'/about'>
      {}
    • ExtractParams<'/users/:id'>
      { id: string }
    • ExtractParams<'/users/:id/posts/:postId'>
      { id: string; postId: string }
    • ExtractParams<'/:org/:repo/issues/:number'>
      { org: string; repo: string; number: string }

    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 23 de julio de 2026

    La solución

    type ExtractParams<Path extends string> = Prettify<
      Path extends `${string}:${infer Param}/${infer Rest}`
        ? { [K in Param]: string } & ExtractParams<`/${Rest}`>
        : Path extends `${string}:${infer Param}`
          ? { [K in Param]: string }
          : {}
    >

    El error más común

    type ExtractParams<Path extends string> =
      Path extends `${string}:${infer Param}/${infer Rest}`
        ? { [K in Param]: string } & ExtractParams<`/${Rest}`>
        : Path extends `${string}:${infer Param}`
          ? { [K in Param]: string }
          : {}

    Todo aquí es correcto salvo la forma de la respuesta. Esto produce `{ id: string } & { postId: string }`, que es asignable a `{ id: string; postId: string }` pero no es el mismo tipo — y las comprobaciones exigen igualdad exacta. Envolverlo todo en `Prettify` colapsa la intersección en un solo objeto.

    Línea por línea

    1. `${string}:${infer Param}/${infer Rest}`

      El `${string}` inicial absorbe lo que haya antes de los dos puntos, así que al patrón no le importa que la ruta empiece por `/users`. `Param` liga hasta la siguiente barra; `Rest` toma todo lo demás.

    2. ExtractParams<`/${Rest}`>

      La barra se repone antes de recurrir. Sin ella, un segmento final como `posts/:postId` seguiría encajando en el primer patrón y la recursión no terminaría limpiamente.

    3. Path extends `${string}:${infer Param}`

      El segundo patrón no lleva barra final, así que solo encaja cuando el parámetro es lo último de la cadena. Ese es el caso base que detiene la recursión.

    4. Prettify<...>

      Vuelve a mapear sobre las claves acumuladas y produce un tipo objeto nuevo. El `& {}` al final de `Prettify` es lo que obliga a TypeScript a evaluar de verdad el tipo mapeado en vez de mantenerlo perezoso.

    Para recordar

    Los patrones de literal de plantilla emparejan con avidez desde la izquierda. Si acumulas tipos objeto mediante recursión obtienes una intersección, y las comprobaciones de igualdad exacta la rechazarán — aplánala antes de devolverla.

    Usa