Mastering TypeScript's keyof Keyword
The keyof operator is essential for type-safe TypeScript code. Let's explore how it works.
What is keyof?
keyof produces a union of the keys of an object type.
interface User {
id: number;
name: string;
email: string;
}
type UserKeys = keyof User;
// Result: "id" | "name" | "email"Basic Usage Example
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const product = {
id: "1",
title: "Laptop",
price: 999
};
const title = getProperty(product, "title"); // Type: string
const price = getProperty(product, "price"); // Type: number
// ❌ Error
const invalid = getProperty(product, "invalid");Real-World Example 1: Type-Safe Form Handler
interface FormData {
username: string;
email: string;
age: number;
}
type FormErrors = {
[K in keyof FormData]?: string;
};
class FormValidator {
private errors: FormErrors = {};
setError<K extends keyof FormData>(field: K, message: string) {
this.errors[field] = message;
}
getError<K extends keyof FormData>(field: K) {
return this.errors[field];
}
}
// Usage
const validator = new FormValidator();
validator.setError("username", "Too short"); // Type-safe!Real-World Example 2: Event Emitter
interface Events {
login: { userId: string; timestamp: number };
logout: { userId: string };
error: { message: string; code: number };
}
class TypeSafeEventEmitter {
private listeners: {
[K in keyof Events]?: Array<(data: Events[K]) => void>;
} = {};
on<K extends keyof Events>(
event: K,
callback: (data: Events[K]) => void
) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(callback);
}
emit<K extends keyof Events>(event: K, data: Events[K]) {
this.listeners[event]?.forEach(cb => cb(data));
}
}
// Usage
const emitter = new TypeSafeEventEmitter();
emitter.on("login", (data) => {
// data is typed: { userId: string; timestamp: number }
console.log(`User ${data.userId} logged in`);
});Advanced: Mapped Types with keyof
// Make all properties optional
type Partial<T> = {
[K in keyof T]?: T[K];
};
// Make all readonly
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
// Pick specific properties
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};Best Practices
1. Use with generics for flexibility 2. Constrain type parameters with K extends keyof T 3. Leverage index access T[K] 4. Document complex types
Conclusion
The keyof operator enables:
- Type-safe property access
- Dynamic key handling
- Better IDE autocomplete
- Fewer runtime errors
Master keyof for robust TypeScript!
Topic Hub
Frontend Architecture / Tooling
Architecture, platform choices, and AI-assisted development workflows.
Open Frontend Architecture / Tooling hubRelated Reading
14 min read
Serverless & Edge Architecture for Full-Stack Apps
Master serverless and edge computing patterns for building scalable, cost-effective full-stack applications. Learn when to use each approach and how to implement them.
12 min read
AI-Assisted Development Tools Every Web Developer Should Use in 2025
Discover the AI-powered tools transforming web development workflows, from code generation to design-to-code, and how to integrate them effectively.
Need a frontend roadmap that supports growth, not churn?
I help product and marketing teams simplify stack decisions, reduce frontend drag, and ship faster without creating long-term maintenance debt.
Written by Salman Izhar
Frontend Developer specializing in React, Next.js, and building high-converting web applications.
Learn More