Mapped types in TypeScript
TypeScript provides a way to get a new type based on an existing one with the aid of mapped types. If you want to alter each base type’s property in the same way, you should definitely go for the mapped types.
In this post I’ll present some common situations when the mapped types are really useful.
Suppose you have the Car interface which allows to alter the mutableCar object’s properties once it has been created.
One day you decide to switch to the immutable updates pattern, hence you must not change an object’s property as in the above example. With mapped types you can easily get the constraint by using the Readonly generic type.
Under the hood TypeScript adds to each Car’s property the readonly modifier, therefore you cannot alter the immutableCar’s name value.
Sometimes you are given a complex interface. You may incrementally add properties to an object which finally results in an object conforming to the given interface. At some stages you only need to have a constraint that you won’t be able to add properties which are not present in the considered interface (valid for object literals only). In general, if you want to claim that all object’s properties are optional, you can use the Partial mapped type.
In certain scenarios you have an interface with some optional properties. However, sometimes you cannot rely on such contract and you need a stricter constraint. Meet the Required mapped type.
The Pick mapped type is my favorite one. With its aid you can get a new type by picking given properties from a source type. Let’s assume that you have the Car interface which includes an id property added automatically as a result of successful post request to a server. An object that will be sent to the server (car form’s value) will probably have each property of the Car interface except for the id. Again, mapped types to the rescue!
However, it would get a little bit lengthy if the Car interface had more properties. You can refactor the above code with the aid of another TypeScript feature, namely conditional types (in particular the Exclude one).
Using the Exclude, you get a string literals union of all the Car’s properties except for the id.
Be strict about null
I always set the strict property in a tsconfig to true, hence it’s no allowed to assign a null value to a variable unless it’s typed as null explicitly. However, sometimes I have to initially set an object’s properties to null. If you have an interface describing an object shape you can use the definition to get an object with possibly null values with the aid of the Nullable mapped type.
Since the Nullable is not provided by TypeScript out of the box, you need to define the type yourself .
I hope that this post gave you a short and clear introduction to the concept of mapped types in TypeScript. There are situations when I find them really useful, hence it’s always worth having them in your tool belt. In addition to several mapped types provided by TypeScript, you can also create new ones yourself.