Module lessons (2/2)
Mapped Types
Mapped types allow you to create new types by transforming the properties of existing ones, one by one. They are built on top of loop syntax over keys using the keyof operator.
type Mapped<T> = {
[P in keyof T]: T[P];
};This example shows a mapped type identical to the original one: it iterates over each key P in keyof T and assigns the same type T[P].
Mutability and Optionality Modifiers
We can add or remove modifiers like readonly and ? (optionality) by prefixing them with + (add, default) or - (remove).
For example, to remove optionality from all properties of a type (making them required):
type Concrete<T> = {
[P in keyof T]-?: T[P];
};The -? modifier removes the optionality flag from each property.
Key Remapping with as
In TypeScript 4.1+, you can remap keys in a mapped type using the as clause and template literal types.
type WriteSetters<T> = {
[K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};Here we are changing the name of each property K to set[CapitalizedKey] and modifying its type to a setter function.
Try it yourself
Exercise 1: Making Properties Nullable
Declare a generic mapped type Nullable<T> that takes an object T and transforms every property so that it can also accept the value null (e.g. T[K] | null).
Show hint
Use the syntax [K in keyof T]: T[K] | null; inside the mapped type object.
Solution available after 3 attempts
Exercise 2: Generating Dynamic Getters with as
Create a mapped type named GetterNames<T> that transforms the keys of the object T by prefixing them with 'get' and capitalizing the original key (use Capitalize). For example, if a key is name, it should become getName. Set the type of the properties to () => T[K].
Show hint
Use as \`get\${Capitalize<string & K>}\` to remap the key and () => T[K] as the property return type.
Solution available after 3 attempts