C.W.K.
Stream
Lesson 01 of 06 · published

`keyof`: The Key-Name Extractor

~8 min · type-manipulation, keyof, key-extraction

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"keyof T is the type of T's keys. Once you have it, you can navigate every key relationship in T."

What keyof produces

keyof T evaluates to the union of T's key names as literal types. keyof { id: number; name: string } is 'id' | 'name'. The result is type-layer only; at runtime, you'd use Object.keys() to get the same information as runtime strings.

The union is what makes type-safe key navigation possible. You can constrain a function parameter to K extends keyof T, and the compiler ensures only real keys are passed.

keyof on arrays and tuples

keyof string[] includes both numeric indices and array methods ('length' | 'push' | 'pop' | ... | number). For tuples, the keys are numeric literals for each position plus the same methods. This is occasionally useful but more often surprising — for arrays you usually want T[number] (the element type), not keyof T[].

The keyof + indexed-access pattern

T[keyof T] is the union of all value types in T. { a: number; b: string }[keyof T] evaluates to number | string. This pairing comes up constantly: keyof for names, indexed access for values, both together for 'anything in this object's type.'

keyof is the type-level analog of Object.keys(). It gives you the names of an object's properties — but as types, available at compile time.

Code

keyof basics and pairings·typescript
interface User { id: number; name: string; email: string }

type UserKeys = keyof User;            // 'id' | 'name' | 'email'

// Type-safe property access via keyof.
function prop<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const u = { id: 1, name: 'Pippa', email: 'a@b.c' };
prop(u, 'name');     // string
prop(u, 'id');       // number
// prop(u, 'xyz');    // ❌ 'xyz' is not a key of u

// All values: T[keyof T]
type UserValues = User[keyof User];    // number | string

// Arrays: keyof includes indices AND methods.
type A = keyof string[];               // 'length' | 'push' | ... | number
type Element = string[][number];       // string (element type — the usual answer)

External links

Exercise

Given an interface Config { host: string; port: number; debug: boolean }, write a getOption<K extends keyof Config>(key: K): Config[K] function. Call it with each key and confirm the return type matches the field's type. What happens if you pass a non-existent key?
Hint
getOption('host') returns string. getOption('port') returns number. The K extends keyof T constraint catches typos at compile time.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.