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.
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.
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.