TypeScript Keyof
The keyof operator turns the properties of a type into a union of string, number, or symbol literal types, letting you write functions that are safely constrained to an object's actual keys.
Turning Properties Into a Type
keyof is a type-level operator, not a runtime function. Given a type T, keyof T produces a union of every property name of T as a literal type. It's the compile-time counterpart to what Object.keys() gives you at runtime, except the compiler checks it for you.
Basic keyof
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
type UserKeys = keyof User;
// "id" | "name" | "email" | "isActive"
const key: UserKeys = "name"; // OK
// const bad: UserKeys = "age"; // Error: not assignable
console.log(key);Safe Property Access With Generics
The most common pattern pairs keyof with a generic constraint: K extends keyof T. This lets a function accept any key of an object while TypeScript infers the exact return type for that key, rejecting typos at compile time.
Generic getProperty
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Ada", email: "ada@example.com", isActive: true };
const name = getProperty(user, "name"); // string
const active = getProperty(user, "isActive"); // boolean
// getProperty(user, "age"); // Error: "age" is not a key of user
console.log(name, active);keyof typeof for Object Literals
- Building typed pick/omit helpers around arbitrary objects
- Restricting form-field names to keys that actually exist on a model
- Typing Redux-style selector maps keyed by state slice
- Creating enum-like lookup tables with keyof typeof
- Powering autocomplete for dynamic property lookups in editors
keyof typeof with a const object
const roleLevel = {
admin: 3,
editor: 2,
viewer: 1,
} as const;
type Role = keyof typeof roleLevel; // "admin" | "editor" | "viewer"
function hasAccess(role: Role, required: number): boolean {
return roleLevel[role] >= required;
}
console.log(hasAccess("editor", 2)); // trueExercise: TypeScript Keyof
What does the `keyof` operator produce from an object type?