Mapped types
Mapped Types в TypeScript позволяют создавать новые типы на основе существующих, применяя преобразования к каждому свойству.
🚀Mapped Types помогают гибко манипулировать типами, уменьшая дублирование кода.
Основные возможности:
-
Итерация по ключам
Можно перебрать ключи одного типа (keyof) и создать новый:type Optional<T> = { [K in keyof T]?: T[K] };Это сделает все свойства
Tнеобязательными. -
Модификаторы (
readonly,?)
Можно добавлять или удалять модификаторы:type Readonly<T> = { readonly [K in keyof T]: T[K] };
type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // Удаляет `readonly` -
Фильтрация ключей
Черезasв TypeScript 4.1+ можно фильтровать или преобразовывать ключи:type OnlyStrings<T> = { [K in keyof T as T[K] extends string ? K : never]: T[K] };
Примеры встроенных mapped types:
Partial<T>– все свойства необязательные.Required<T>– все свойства обязательные.Pick<T, K>– выбирает только указанные ключиKизT.Record<K, V>– создаёт тип с ключамиKи значениямиV.
Пример из практики:
interface Movie {
title: string;
director: string;
awards?: string;
}
type Keys = keyof Movie; // это обычный union 'title' | 'director' | 'awards'
// Mapped type
type MovieCopy = {
[Property in keyof Movie]: number; // Property переменная, в результате просто изменится тип на number у всех ключей
};
// делаем все поля только для чтения
type ReadonlyMovie = {
readonly [Property in keyof Movie]: Movie[Property];
};
// делаем все поля опциональными
type OptionalMovie = {
readonly [Property in keyof Movie]?: Movie[Property];
};
// делаем все поля обязательными
type RequiredMovie = {
readonly [Property in keyof Movie]-?: Movie[Property];
};
// убираем readonly из всех полей
type EditableMovie = {
-readonly [Property in keyof Movie]-?: Movie[Property];
};
type MovieSetters = {
[Property in keyof Movie as `set${Capitalize<Property>}`]-?: (
value: Movie[Property]
) => void;
};
type MovieGetters = {
[Property in keyof Movie as `set${Capitalize<Property>}`]-?: () => Movie[Property];
};