TypeScript Mapped types

Jayed Talukder
3 min readJan 1, 2024

--

Sometimes, you may need slight changes to a type. Instead of writing a whole new type, we can take advantage of some operators or utility types to produce such desired types.

Using the keyof operator

The following snippet demonstrates allowing the property securityGroup to contain undefined

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type userWithOptionalSecurityGroup = {
[K in keyof User]: K extends 'securityGroup' ? User[K] | undefined : User[K];
}; // now the securityGroup can be assigned either a string or undefined

Enforcing/removing the ‘?’ and ‘readonly’ keyword using ‘+’ and ‘-’ mapping modifier

(also using the ‘as’ clause)

By prefixing + or to those keywords, you can explicitly enforce or remove them from the original type as demonstrated below:

type User = {
readonly id: string;
name: string;
readonly securityGroup: string;
level?: number;
}

type MutableUser = {
-readonly [K in keyof User] : User[K]
}

type MaybeUser = {
[K in keyof User] -?: User[K]
}

type ReadonlyUser = {
+readonly [K in keyof User as `readonly_${K}`] -?: User[K]
}

// the usage of + is not much efficient since there are dedicated utility
// types for this purpose (more on it later)

Using the built-in utility types Pick<T, K> & Omit<T, K>

Often times, it is desired to only pick a handful of the properties from a type, or remove certain properties:

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type MinimalUserO = Omit<User, 'name' | 'level'>; // when you know
// which keys to discard from the type User
type MinimalUserP = Pick<User, 'id' | 'securityGroup'>; // when you know
// which keys to keep from the type User

Using the keyof operator in combination with Pick<T, K> & Exclude<U, E>

the snippet below is an extended example using Pick<Type, Keys> and Exclude<UnionType, ExcludedMembers>. Please notice carefully that, the Utility type Pick<T, K> works on a type, whereas Exclude<UT, EM> works on a union type. Hence, below is a demonstrable example of Exclude<UT, EM> that takes advantage of the keyof operator:

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type MinimalUserEx = Pick<User, Exclude<keyof User, 'name' | 'level'>>;
// the same result can be achieved using Omit<T, K>

Using the built-in utility type Partial<T>

This utility type turns all the properties of a type into optional:

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type OptionalUser = Partial<User>; // all properties of User set to optional

Using the built-in utility type Readonly<T>

This utility type turns all the properties of a type into readonly. Assigning values to the properties of this new mapped type is not possible:

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type ReadOnlyUser = Readonly<User>; // all properties of User set to readonly

Using the built-in utility type Required<T>

This utility type turns all the properties of a type into required:

type User = {
id: string;
name: string;
securityGroup: string;
level?: number;
}

type ReadOnlyUser = Required<User>; // all properties of User set to required

--

--

Jayed Talukder
Jayed Talukder

Written by Jayed Talukder

0 Followers

10 years into coding, architecting & mentoring. https://www.linkedin.com/in/jayedtz/

No responses yet