keyof: A Union Type of an Object's Keys
`keyof` is like `Object.keys()` for the type system, creating a union type of an object's property names. It's used to write generic functions that safely access properties on unknown objects.
WHY IT EXISTS: TypeScript needs a way to create generic functions that can safely operate on object properties without knowing the object's specific shape in advance. The keyof operator provides this bridge, allowing developers to work with property keys as a distinct type, enabling powerful type manipulation.
THE MENTAL MODEL: Think of keyof as a compile-time version of JavaScript's Object.keys(). Instead of returning an array of strings at runtime, keyof inspects a type and returns a union type of all its possible key names, which TypeScript can then use for static analysis.
HOW IT WORKS: The keyof operator is applied to a type, not a value. For a standard object type like type Point = { x: number; y: number; }, the expression keyof Point evaluates to the literal union type "x" | "y". If the object type includes an index signature, keyof returns the type of the indexer. For type Arrayish = { [n: number]: unknown; }, keyof Arrayish is number. The main footgun is with string index signatures: for type Mapish = { [k: string]: boolean; }, keyof Mapish is string | number. This is because JavaScript object keys are always coerced to strings at runtime (e.g., obj[0] is the same as obj["0"]), and TypeScript's type system reflects this behavior for safety.
WHEN TO USE IT: Use keyof to constrain generic type parameters. This is essential for writing reusable utility functions that access object properties dynamically. For instance, a function that plucks a property from an object can use keyof to ensure the provided key name is valid for that object, preventing runtime errors. It's a fundamental building block for advanced mapped types.
WHEN NOT TO USE IT: Avoid keyof for simple, direct property access. If you know the object's shape and the specific key you need, obj.propertyName is far clearer and more direct. keyof is for abstraction and generic programming, not for cases where the key is static and known.
ONE CANONICAL EXAMPLE: A type-safe property accessor function demonstrates keyof perfectly. First, define a type: type User = { id: number; name: string; }. Then, create a generic function: function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; }. The constraint K extends keyof T ensures that the key argument must be one of the keys of the obj type. You can call it like getProperty(user, 'name'), which is type-safe. A call like getProperty(user, 'age') would result in a compile-time error because 'age' is not a key of User.
Read the original → typescriptlang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.