Saltar al contenido
webtype.orgwebtype.org

    ↑↓ mover · ⏎ abrir · esc cerrar

    Concepto 7 de 12

    infer

    infer es emparejamiento de patrones. Describes la forma que esperas, pones infer X donde está la parte interesante, y el compilador resuelve X. Casi todos los helpers de extracción de la librería estándar son un condicional con un infer bien colocado.

    Sigue el tipoVerificado por el compilador
    ExpresiónItem<string[]>
    Se resuelve astring
    ExpresiónItem<number[]>
    Se resuelve anumber
    ExpresiónItem<boolean>
    Se resuelve anever

    Busca un array y captura el tipo de sus elementos como U. Un tipo que no sea un array no coincide.

    Definición del tipo
    type Item<T> = T extends (infer U)[] ? U : never

    Funciona en cualquier sitio donde quepa un tipo

    type Unwrap<T> = T extends Promise<infer Inner> ? Inner : T
    type Element<T> = T extends (infer E)[] ? E : never
    type Returns<T> = T extends (...a: never[]) => infer R ? R : never
    type Head<T> = T extends [infer H, ...unknown[]] ? H : never
    type Rest<S> = S extends `${string}-${infer R}` ? R : never

    Promesas, arrays, retornos de función, posiciones de tupla, patrones de cadena — el mecanismo es idéntico cada vez. Solo cambia la forma que lo rodea, y por eso aprender uno te enseña todos.

    Restringir lo que se liga

    // Without the constraint, F is unknown and cannot be
    // interpolated into a template literal.
    type First<T> = T extends [infer F extends string, ...unknown[]]
      ? `${F}!`
      : never

    Un infer puede llevar su propia cláusula extends, que acota lo que liga y permite usar el resultado donde se exige un tipo concreto. Sin ella sueles obtener unknown, y el error aparece una línea después de la causa.

    El error más común

    // Intent: get the return type of any function.
    type Returns<T> = T extends () => infer R ? R : never
    
    Returns<() => string>          // string
    Returns<(a: number) => string> // never — pattern demands zero parameters
    
    // Fixed: never[] in parameter position accepts any signature,
    // because parameters are checked contravariantly.
    type Returns2<T> = T extends (...a: never[]) => infer R ? R : never

    El patrón debe ser tan permisivo como las entradas que quieras emparejar. Un tipo de función sin parámetros solo encaja con funciones sin parámetros, así que todo lo demás cae en silencio en la rama falsa.

    Ejercicio

    Extrae el tipo de elemento de un tipo de array.

    Pruébalo

    2
    • ElementOf<string[]>—
      → string
    • ElementOf<number>—
      → never

    Para recordar

    Describe la forma, marca el hueco con infer y deja que el compilador lo rellene. Si nada encaja, el patrón es más estricto que la entrada — no al revés.

    Se practica en