The Keys of a Type, as a Union
`keyof`
`keyof T` is a union of T's property names. The foundation of type-safe property access.
What you'll learn
- Use `keyof` to get a property-name union
- Combine with generics for type-safe access
- Recognize `keyof` on union types
keyof T evaluates to a union of T’s property names. The
foundation of type-safe property access.
The Basics
type User = {
name: string;
age: number;
admin: boolean;
};
type UserKeys = keyof User;
// "name" | "age" | "admin" Type-Safe Property Access
The classic use:
function get<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const u: User = { name: "Ada", age: 36, admin: true };
get(u, "name"); // string
get(u, "age"); // number
get(u, "admin"); // boolean
get(u, "missing"); // ✗ Argument of type '"missing"' is not assignable... K extends keyof T restricts the key argument to valid keys. The
return type T[K] is the type of that specific property.
keyof on Records
type Scores = Record<string, number>;
type K = keyof Scores; // string | number — `Record<string, ...>` allows numeric keys too Record’s keys aren’t necessarily literal — keyof reflects that.
keyof on Index Signatures
type Settings = { [key: string]: boolean };
type K = keyof Settings; // string | number A plain string index signature includes number in its keyof
(legacy JS thing — number keys coerce to strings).
keyof on a Union
type A = { x: number; y: number };
type B = { x: number; z: number };
type K = keyof (A | B); // "x" (the common keys) keyof (A | B) is the INTERSECTION of keyof A and keyof B —
only keys that exist on every member.
keyof (A & B) is the UNION — all keys from both.
keyof with No Keys
type Empty = {};
type K = keyof Empty; // never (no keys exist) Up Next
typeof — getting the type of a value.