Advanced · 18 min
Template literals and key remapping
Derive related string keys while preserving the corresponding property types.
Build constrained string names
Template literal types combine literal unions into new string unions. They can keep a small event-name convention consistent. They do not validate arbitrary runtime strings, and large unions can expand into many combinations.
type Field = "name" | "city";
type EventName = `${Field}Changed`;
const event: EventName = "cityChanged";
console.log(event);Output
cityChanged
Rename keys in a mapped type
The "as" clause remaps keys. Intersecting a key with string allows string transformations, and the indexed access preserves each original value type. The example creates getter names in the type system; the functions still need implementations.
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] };
type Profile = { name: string; score: number };
const getters: Getters<Profile> = { getName: () => "Ada", getScore: () => 7 };
console.log(getters.getName() + ": " + getters.getScore());Output
Ada: 7
Put it into practice
- Predict the output and explain which relationships the types enforce.
- Fix the task while preserving its type contract, then check both practice questions.
Try it yourself
Code runs on this device. When you are signed in, drafts sync to your account.
Implement a correctly typed getter
Make "getScore" return the number 7, preserving the getter contract.
The getter return type comes from the original numeric property.
Show solution
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] };
type Profile = { name: string; score: number };
const getters: Getters<Profile> = { getName: () => "Ada", getScore: () => 7 };
console.log(getters.getName() + ": " + getters.getScore());Key remapping changes names without changing the associated value types. Returning a number satisfies the generated score getter contract.