Часто бывает так, что нужно взять существующий тип Person
и сделать каждое из его свойств необязательным. Используя mapped types, получим:
interface Person {
name: string;
age: number;
location: string;
}
type Partial<T> = {
// К каждому свойству типа <T> добавляем знак `?`.
[P in keyof T]+?: T[P];
};
type PartialPerson = Partial<Person>;
// Теперь type PartialPerson выглядит так:
type PartialPerson = {
name?: string | undefined;
age?: number | undefined;
location?: string | undefined;
};
Также, можно создать тип с полями только для чтения (readonly) или с обязательными полями:
// Сохраняет типы одинаковыми, но делает каждое свойство доступным только для чтения (readonly).
type Readonly<T> = {
+readonly [P in keyof T]: T[P];
};
// Сохраняет типы одинаковыми, но делает каждое свойство обязательным (required).
type Required<T> = {
[P in keyof T]-?: T[P];
};
Кроме того, если у тебя есть не обязательные вложенные свойства, например:
interface Person {
name: string;
age: number;
location?: Location;
}
interface Location {
country: string;
city?: string;
street?: string;
}
И ты хочешь сделать все свойства обязательными - можно сделать таким образом:
type DeepRequired<T> = {
[P in keyof T]-?: DeepRequired<T[P]>;
};
type RequiredPerson = DeepRequired<Person>;
Перебирает каждое свойство типа и удаляет необязательный знак ?
.
Важно! Каждое свойство должно быть типом, иначе
DeepRequired
не будет работать. Например, как здесь:
interface Person {
name: string;
age: number;
location?: {
country: string;
city?: string;
street?: string;
};
}
Подробнее о модификаторах перебора типов.