---
sidebar_position: 6
---

# Mapped types

**Mapped Types** в TypeScript позволяют создавать новые типы на основе существующих, применяя преобразования к каждому свойству.

🚀**Mapped Types** помогают гибко манипулировать типами, уменьшая дублирование кода.

## Основные возможности:
1. **Итерация по ключам** \
    Можно перебрать ключи одного типа (**`keyof`**) и создать новый:
    ```ts
    type Optional<T> = { [K in keyof T]?: T[K] };
    ```
    Это сделает все свойства **`T`** необязательными.

2. **Модификаторы** (`readonly`, `?`) \
   Можно добавлять или удалять модификаторы:
   ```ts
    type Readonly<T> = { readonly [K in keyof T]: T[K] };
    type Mutable<T> = { -readonly [K in keyof T]: T[K] }; // Удаляет `readonly`
    ```
   
3. **Фильтрация ключей** \
   Через **`as`** в TypeScript 4.1+ можно фильтровать или преобразовывать ключи:
   ```ts
    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`.

Пример из практики:

```ts
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];
};
```