The keyof operator
What keyof does
keyof takes the type of an object (interface, class, literal, and so on)
and returns a union of all its keys as string (or numeric) literals.
Syntax:
keyof Twhere T is the type whose keys you want to extract.
Example 1. A basic example
type User = {
id: number;
name: string;
isAdmin: boolean;
};
type Keys = keyof User;
// "id" | "name" | "isAdmin"keyof User returned a union of literal key types
"id" | "name" | "isAdmin".
How it works
keyof does not return values; it creates a type
that represents the set of property names of an object.
You can think of it as an
Object.keys()operator
- but one that works at the type level, not at runtime.
Example 2. With a type with numeric keys
type Matrix = {
0: string;
1: string;
2: string;
};
type K = keyof Matrix;
// "0" | "1" | "2"All keys become string literals, even if the object had numbers.
Example 3. Used with Record
type Permissions = Record<"read" | "write" | "delete", boolean>;
type K = keyof Permissions;
// "read" | "write" | "delete"Example 4. Used with typeof
keyof is often used together with typeof
to extract keys from a real object:
const user = {
id: 1,
name: "Tom",
isAdmin: true,
};
type UserKeys = keyof typeof user;
// "id" | "name" | "isAdmin"
typeof userturns the object into its type,keyof typeof userextracts the key names.
Example 5. Paired with Index Access Types
keyof is usually used together with the indexing operator T[K].
type User = {
id: number;
name: string;
};
type ValueOfUser = User[keyof User];
// number | stringThis gives you the type of all the object's values,
similar to Object.values() in JS.
Example 6. Constraining generic parameters
keyof is often used to constrain generics
so that only valid keys can be passed.
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { id: 1, name: "Alex" };
getProp(user, "id"); // OK
getProp(user, "email"); // Error: "email" is not a key of userK extends keyof T says:
"K must be one of the keys of type T".
Example 7. Applying it to classes
class Point {
x = 0;
y = 0;
move(dx: number, dy: number) {}
}
type Keys = keyof Point;
// "x" | "y" | "move"Example 8. With optional and readonly properties
keyof does not change property modifiers (readonly, ?)
- it simply returns the names.
type Config = {
readonly url: string;
timeout?: number;
};
type Keys = keyof Config;
// "url" | "timeout"Example 9. Applying it to unions
If a type is a union of objects,
keyof returns the intersection of their keys (only the shared ones):
type A = { a: number; shared: string };
type B = { b: boolean; shared: string };
type Keys = keyof (A | B);
// "shared"Example 10. Applying it to arrays
Arrays in TS are objects, so they have keys too:
type K = keyof string[];
// number | "length" | "toString" | ...So
keyofreturns both the numeric indices and the standard array methods.
Applying it in practice
Validating keys
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
const result = {} as Pick<T, K>;
for (const key of keys) {
result[key] = obj[key];
}
return result;
}
const user = { id: 1, name: "John", isAdmin: true };
const partial = pick(user, ["id", "name"]); // worksSummary
| Concept | Description |
|---|---|
keyof T | Returns a union of the key names of type T |
| Result type | String/numeric literal key types |
| Typical use | K extends keyof T, T[keyof T], keyof typeof obj |
| JS analog | Similar to Object.keys(obj) - but works at the type level |
| Used in | Pick, Record, Partial, Omit, generic functions, and more |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.