Why lookup types matter
They keep types in sync with their sources without repetition:
const keys = ["host", "port"] as const;
type Key = typeof keys[number]; // "host" | "port"
typeof keys[number] reads the element type of a tuple. This pattern derives a type directly from a real value, so renaming a key cannot desync the type.
Mapped + lookup combos
Combine lookup with mapped types for powerful transforms:
type PromiseAll<T> = {
[K in keyof T]: Promise<T[K]>;
};
interface Models { user: User; post: Post; }
type AsyncModels = PromiseAll<Models>; // { user: Promise<User>; ... }
This wraps every property in a Promise, iterating the source's keys. It is exactly how Promise.all's type is expressed.