← Back to TypeScript Course | Chapter 7: Generics | Lesson 6 of 8

Keyof Operator

The keyof operator creates a union of the property keys of a type, and pairs naturally with typeof, mapped types, and generic constraints to build type-safe utilities from existing object shapes.

Basic keyof

For an object type, keyof produces a union containing its known property names as string literal types, letting code work generically with 'any valid key of this type' instead of a fixed, hardcoded key.

Example: Basic keyof

typescript
interface User {
  id: number;
  name: string;
}
type UserKeys = keyof User; // "id" | "name"
let key: UserKeys = "name";
console.log(key);

keyof with Generic Functions

The K extends keyof T pattern ensures that a supplied key genuinely exists on the object type T, catching typos in a property name at compile time instead of returning undefined silently at runtime.

Example: keyof with Generic Functions

typescript
function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}
const user = { id: 1, name: "Wei" };
console.log(getProperty(user, "name"));

keyof and Return Types

The indexed access type T[K] represents the type of the property selected by K, so a function's return type can automatically match whatever property was actually requested, rather than being widened to any.

Example: keyof and Return Types

typescript
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}
const user = { id: 1, name: "Wei" };
const name: string = getProperty(user, "name");
console.log(name);

keyof for Updating Properties

The same K extends keyof T pattern can type both a selected property key and its matching value together, which is exactly what a type-safe generic getter or setter function needs.

Example: keyof for Updating Properties

typescript
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
  obj[key] = value;
}
const user = { id: 1, name: "Wei" };
setProperty(user, "name", "Lin");
console.log(user);

keyof with Interfaces

Interfaces can be combined with keyof and generics to build reusable property-reading utilities that stay fully type-checked across any interface shape they're applied to.

Example: keyof with Interfaces

typescript
interface Product {
  id: number;
  price: number;
}
function getValue<K extends keyof Product>(product: Product, key: K) {
  return product[key];
}
console.log(getValue({ id: 1, price: 20 }, "price"));

Keyof with Mapped Types

A mapped type can iterate over keyof T using the syntax { [K in keyof T]: ... }, which visits every property name of T one at a time, letting a new type be generated that mirrors T's keys while transforming each property's value type.

Example: Keyof with Mapped Types

typescript
interface User {
  id: number;
  name: string;
}
type ReadonlyUser = { readonly [K in keyof User]: User[K] };
const user: ReadonlyUser = { id: 1, name: "Sana" };
console.log(user);

The typeof Operator

In a type position, typeof takes an existing variable or constant and produces the type TypeScript already inferred for it, which avoids re-declaring a type by hand and keeps the type automatically in sync whenever the value's shape changes.

Example: The typeof Operator

typescript
const config = { retries: 3, timeout: 1000 };
type ConfigType = typeof config; // { retries: number; timeout: number }
let another: ConfigType = { retries: 5, timeout: 2000 };
console.log(another);

Keyof Typeof Pattern

Combining keyof with typeof, as in keyof typeof someObject, produces a union of a runtime object's own property names as string literal types, which is a common way to derive a type-safe key set directly from a plain JavaScript object.

Example: Keyof Typeof Pattern

typescript
const colors = { red: "#f00", green: "#0f0" };
type ColorKey = keyof typeof colors; // "red" | "green"
let key: ColorKey = "red";
console.log(colors[key]);

Keyof with Generic Constraints on Records

The keyof operator also works well with Record<K, V> and multiple type parameters, letting a function constrain one generic parameter to be a key of another, which is useful for utilities that operate generically over any object's keys and values together.

Example: Keyof with Generic Constraints on Records

typescript
function getFromRecord<K extends keyof R, R extends Record<string, number>>(record: R, key: K) {
  return record[key];
}
const scores = { math: 90, science: 85 };
console.log(getFromRecord(scores, "math"));
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.