const STATUS = {
idle: "Idle",
loading: "Loading…",
error: "Something went wrong",
} as const;
type StatusKey = keyof typeof STATUS; // "idle" | "loading" | "error"
type StatusLabel = (typeof STATUS)[StatusKey]; // the three label literals
type User = { id: number; address: { city: string } };
type City = User["address"]["city"]; // string
typeof gets the type of a value. keyof gets the keys of an object type as a union. An indexed access type T[K] gets the type of a property.
typeof in a type position takes a runtime value and gives you its type. So you can define data once and build types from it.
keyof takes an object type and gives the union of its keys.
An indexed access type T[K] looks up the type of a property. K can be:
- a single key, like
User["id"] - a union of keys
- a nested path, like
User["address"]["city"]
For arrays, T[number] gives the element type.
Combined:
keyof typeof STATUSgives the keys of a runtime object as a union.(typeof STATUS)[StatusKey]gives its values.
With as const, those values are literal types. This pattern keeps a lookup table and its types in one place.
typeofin a type position gets the type of a runtime value.keyofgives a union of an object type's keys.T[K]reads a property type, andT[number]reads an array element type.keyof typeof objbuilds a union of keys from runtime data.
Read more