TypeScript keyof

Extract object keys as types

🔑 What is keyof?

The keyof operator extracts all property keys from an object type as a union. It helps create type-safe code by ensuring you only use valid property names from objects.


type Person = { name: string; age: number };
type PersonKeys = keyof Person; // "name" | "age"
                                    

Key Concepts

🏷️

Extract Keys

Get all property names as types

type User = { id: number; email: string };
type Keys = keyof User; // "id" | "email"
🔒

Type Safety

Prevent invalid property access

function getValue(obj: User, key: keyof User) {
  return obj[key]; // Safe!
}
🔄

Dynamic Access

Access properties dynamically

const user = { id: 1, email: "[email protected]" };
getValue(user, "id"); // ✓ Valid
⚠️

Error Prevention

Catch typos at compile time

getValue(user, "name"); 
// ✗ Error: "name" not in keyof User

🔹 Basic keyof Usage

Extract keys from an object type:

type Product = {
  id: number;
  name: string;
  price: number;
};

type ProductKeys = keyof Product;
// Result: "id" | "name" | "price"

const key1: ProductKeys = "name";    // ✓ Valid
const key2: ProductKeys = "price";   // ✓ Valid
const key3: ProductKeys = "color";   // ✗ Error!

🔹 keyof with Functions

Create type-safe property accessors:

type Car = {
  brand: string;
  model: string;
  year: number;
};

function getProperty(car: Car, key: keyof Car) {
  return car[key];
}

const myCar: Car = {
  brand: "Toyota",
  model: "Camry",
  year: 2023
};

console.log(getProperty(myCar, "brand")); // "Toyota"
console.log(getProperty(myCar, "year"));  // 2023
// getProperty(myCar, "color"); // ✗ Error!

🔹 keyof with Generics

Make reusable type-safe functions:

function getPropertyGeneric<T, K extends keyof T>(
  obj: T, 
  key: K
): T[K] {
  return obj[key];
}

const user = { name: "Alice", age: 30 };
const userName = getPropertyGeneric(user, "name"); // string
const userAge = getPropertyGeneric(user, "age");   // number

🔹 keyof with Arrays and Tuples

keyof works with arrays and tuples too:

// With arrays
type ArrayKeys = keyof string[];
// Result: number | "length" | "push" | "pop" | ...

// With tuples
type Tuple = [string, number, boolean];
type TupleKeys = keyof Tuple;
// Result: "0" | "1" | "2" | "length" | ...

const tuple: Tuple = ["hello", 42, true];
const firstKey: TupleKeys = "0";  // ✓ Valid
const lengthKey: TupleKeys = "length"; // ✓ Valid

🔹 Practical Example

Build a type-safe update function:

type Settings = {
  theme: "light" | "dark";
  fontSize: number;
  notifications: boolean;
};

function updateSetting<K extends keyof Settings>(
  key: K,
  value: Settings[K]
): void {
  // Update logic here
  console.log(`Updated ${key} to ${value}`);
}

updateSetting("theme", "dark");        // ✓ Valid
updateSetting("fontSize", 16);         // ✓ Valid
updateSetting("notifications", true);  // ✓ Valid
// updateSetting("theme", 123);        // ✗ Error: wrong type
// updateSetting("color", "blue");     // ✗ Error: invalid key

💡 Key Takeaways

  • keyof extracts all property keys as a union type
  • Use it to create type-safe property access functions
  • Combine with generics for reusable type-safe code
  • Prevents typos and invalid property access at compile time

🧠 Test Your Knowledge

What does keyof return?