What is keyof operator?
The `keyof` operator in TypeScript is a powerful type query operator used to extract the union type of literal strings or string literals representing the keys of a given object type. It's fundamental for creating type-safe operations that interact with object properties.
What is `keyof`?
When applied to an object type, keyof produces a union type of all public property names (keys) of that object type. This means if you have an interface or type with properties, keyof will give you a type that can be any of those property names as a string literal.
interface User {
id: number;
name: string;
email?: string;
}
type UserKeys = keyof User; // 'id' | 'name' | 'email'
interface Point {
x: number;
y: number;
}
type PointKeys = keyof Point; // 'x' | 'y'
type ArrayKeys = keyof any[]; // number | 'length' | 'toString' | 'pop' | ... (includes all array methods and numeric indices)
type ObjectKeys = keyof { [key: string]: any }; // string | number
type SimpleObjectKeys = keyof { a: number; b: string; }; // 'a' | 'b'
As seen in the examples, keyof User results in a type that is a union of the string literals 'id', 'name', and 'email'. This is incredibly useful for ensuring that when you're referring to a property by its name, you're using a name that actually exists on the object type.
Use Cases
The primary use case for keyof is in conjunction with generic types to create functions or classes that can operate on properties of various object types while maintaining type safety. This prevents runtime errors that might occur if a non-existent property name is used.
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = {
id: 1,
name: "Alice",
email: "alice@example.com"
};
const userId = getProperty(user, "id"); // userId is of type number
const userName = getProperty(user, "name"); // userName is of type string
// const userAge = getProperty(user, "age");
// Argument of type '"age"' is not assignable to parameter of type '"id" | "name" | "email"'. (TypeScript Error)
In the getProperty function, K extends keyof T ensures that the key argument must be a valid key of the object obj. The return type T[K] is an indexed access type, which means TypeScript correctly infers the type of the value at that specific key. This provides robust type checking at compile time, catching errors like attempting to access a non-existent property ('age' in the example) before the code ever runs.
Key Benefits
- Type Safety: Ensures that property names used in operations are valid for a given object type, preventing common runtime errors.
- Improved Refactoring: If a property name changes in an interface, TypeScript will flag all uses of the old name that were typed with
keyof, making refactoring easier and safer. - Powerful Generics: Enables the creation of flexible and reusable generic functions and classes that work with arbitrary object structures while maintaining strong type guarantees.
- Enhanced IntelliSense: Provides better auto-completion suggestions for property names in development environments.