Saltar al contenido
webtype.orgwebtype.org

    ↑↓ mover · ⏎ abrir · esc cerrar

    Concepto 3 de 12

    keyof y acceso indexado

    Estos dos operadores son cómo se desarma un tipo objeto. keyof te da las claves, el acceso indexado te devuelve un tipo de valor. Casi toda transformación útil en esta ruta es esos dos combinados con algo que itera.

    Sigue el tipoVerificado por el compilador
    Expresiónkeyof User
    Se resuelve a"name" | "age"
    ExpresiónUser["name"]
    Se resuelve astring
    ExpresiónUser[keyof User]
    Se resuelve astring | number

    Lee las claves y después el tipo de un valor. Consultar todas las claves produce una unión de sus tipos.

    Definición del tipo
    type User = { name: string; age: number }

    keyof da una unión, no una lista

    interface User { id: number; name: string }
    
    type Keys = keyof User        // 'id' | 'name'
    type Values = User[keyof User] // number | string

    El resultado es una unión de tipos literales de clave, sin orden concreto. No hay forma de pedir «la primera clave» — el orden no forma parte de lo que garantiza un tipo objeto, y depender de él sería depender de un detalle de implementación.

    Indexar con una unión se distribuye

    interface User { id: number; name: string; admin: boolean }
    
    type One = User['id']              // number
    type Some = User['id' | 'name']    // number | string
    type Every = User[keyof User]      // number | string | boolean
    
    type Element = string[][number]    // string

    Indexar con una unión de claves produce la unión de los tipos de valor correspondientes. T[number] sobre un array o tupla es la misma idea, y así se convierte una tupla en una unión de un solo paso.

    El error más común

    interface User { id: number; name: string }
    
    // Intent: the value types of User.
    type Values = keyof User[]
    // Actually parses as keyof (User[]) — the keys of an ARRAY:
    // 'length' | 'push' | 'pop' | ...
    
    type Fixed = User[keyof User]  // number | string

    El [] pospuesto liga más fuerte que keyof, así que esto pide las claves de un array de usuarios en vez de los valores de un usuario. El resultado es una unión enorme de nombres de métodos de array, que luego falla lejos del error real.

    Ejercicio

    Produce la unión de todos los tipos de valor de T.

    Pruébalo

    1
    type User = { id: number; name: string }
    • Values<User>—
      → string | number

    Para recordar

    keyof T abre un objeto y T[K] lee de él. Recurre a ellos antes de escribir un tipo recursivo — sorprendentemente muchos problemas no necesitan nada más.