Saltar al contenido
webtype.orgDoce conceptos · 3/12

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.