Основы Mapped Types

Тренажер по TypeScript для пользователей с начальным уровнем подготовки.

Тренажер по TypeScript

Mapped Types (Сопоставленные типы) — это мощный инструмент в TypeScript, позволяющий создавать новые типы на основе уже существующих, трансформируя их свойства. Это похоже на использование метода .map() для массивов, но применяется к типам.

Основной синтаксис выглядит так: { [P in K]: T }, где K — это набор ключей (обычно Union Type), по которым мы проходимся итерацией. Чаще всего используется оператор keyof для получения всех ключей существующего типа.

С помощью Mapped Types можно легко создавать утилиты, такие как Partial (делает все поля необязательными) или Readonly (запрещает изменение полей), не дублируя код вручную. Это основа принципа DRY (Don't Repeat Yourself) в типизации. В этом уроке мы разберем синтаксис итерации по ключам и базовые преобразования типов.

Список тем

1. Синтаксис итерации

id: 40747_mt_base_replace

В этом задании вам предстоит вспомнить синтаксис Mapped Types в TypeScript. Ниже представлен фрагмент кода, в котором объявлен интерфейс и на его основе создаётся новый тип с помощью Mapped Type. Однако в определении Mapped Type пропущены ключевые слова, необходимые для итерации по ключам исходного интерфейса. Ваша задача — вставить пропущенные ключевые слова в правильные места, чтобы код был синтаксически корректным и создавал ожидаемый тип.

Заполните пропуски
interface User {
  id: number;
  name: string;
  email: string;
}

type ReadonlyUser = {
  readonly [K input1S input2S User]: User[K];
};
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

2. Добавление модификаторов

id: 40747_mt_select_fill_modifiers

В этом задании вам предстоит заполнить пропуски в коде, реализующем пользовательский mapped type, аналогичный встроенному Readonly. Вам нужно выбрать правильный синтаксис для добавления модификатора 'readonly' перед ключом в квадратных скобках. Обратите внимание на расположение ключевого слова 'readonly' и использование оператора 'keyof'.

Нужно правильно расставить в пропуски предложенные варианты
type MyReadonly<T> = {
  input1S [K in keyof T]: T[K]
};

interface Book {
  title: string;
  author: string;
  year: number;
}

type ReadonlyBook = MyReadonly<Book>;
// Теперь все свойства ReadonlyBook доступны только для чтения
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

3. Предсказание типа свойства

id: 40747_mt_predict_type_transform

Проанализируйте приведённый код TypeScript. Дан исходный интерфейс Person и Mapped Type BooleanPerson, который преобразует все свойства этого интерфейса. Внимательно изучите, как изменяются типы свойств, и выберите, каким будет тип конкретного свойства 'age' в результирующем типе BooleanPerson.

Выберите правильный вариант ответа
interface Person {
    name: string;
    age: number;
    isStudent: boolean;
}

type BooleanPerson = {
    [K in keyof Person]: boolean;
};

// Какого типа будет свойство 'age' в типе BooleanPerson?
Сообщения
Проверить
Показать подсказку

4. Исправление синтаксиса Mapped Type

id: 40747_mt_error_syntax

В этом фрагменте кода TypeScript, демонстрирующем использование Mapped Types, допущена синтаксическая ошибка. В определении типа `ReadonlyProps` внутри конструкции `[K in keyof T]` пропущен или неправильно расставлен ключевой символ. Найдите строку с ошибкой и исправьте её, чтобы тип корректно создавал новый тип со всеми свойствами, доступными только для чтения.

Найдите ошибку и исправьте
type ReadonlyProps<T> = {
  [K in keyof T] T[K]
};
 
interface User {
  name: string;
  age: number;
}
 
// После исправления тип ReadonlyProps<User> сделает все свойства доступными только для чтения
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

5. Сборка утилиты Partial

id: 40747_mt_build_partial

Из предложенных строк соберите корректное определение типа MyPartial на TypeScript, который делает все свойства переданного типа опциональными (добавляет знак '?'). В решении должны использоваться только необходимые строки, лишние строки включать не нужно. Обратите внимание на синтаксис mapped types и правильную структуру объявления типа.

Перетяните в правильном порядке строки из одного блока в другой
type MyPartial<T> = {
  [P in keyof T]?: T[P];
};
type Partial<T> = {
  [P in keyof T]: T[P];
type Readonly<T> = {
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

6. Определение итерируемого ключа

id: 40747_mt_click_target_keys

Внимательно изучите приведённый фрагмент кода TypeScript, содержащий определение Mapped Type. Ваша задача — найти и выделить кликом переменную типа, которая представляет собой 'текущий ключ' в итерации (тот самый ключ, который последовательно принимает значения из union-типа или набора ключей объекта). Не отмечайте другие части кода, такие как имена типов, ключевые слова или фигурные скобки.

Кликните по всем фрагментам, которые подходят под условие задания.
type ComplexMappedType<T, U extends keyof T> = {
  [{{P~|~t1}} in {{U~|~t2}}]: T[{{P~|~t3}}] extends string ? {{P~|~t4}} : never;
} & {
  readonly [{{K~|~t5}} in keyof T as {{K~|~t6}} extends string ? {{K~|~t7}} : never]: boolean;
};
Сообщения
Проверить
Показать подсказку

7. Количество ключей

id: 40747_mt_give_result_keys

В данном фрагменте кода TypeScript определён интерфейс с тремя свойствами. Затем с помощью Mapped Type создаётся новый тип, который преобразует каждое свойство исходного интерфейса. Проанализируйте код и определите, сколько свойств будет у результирующего типа после применения Mapped Type. Введите одно число в поле ответа.

Что должно получиться?
interface Person {
    name: string;
    age: number;
    city: string;
}

type ReadonlyPerson = {
    readonly [K in keyof Person]: Person[K];
};
Сообщения
Проверить
Показать подсказку

TypeScript: компиляция и запуск

id: 40747_compiler
TS
Запустить тренажёр (TypeScript)
НайтиКурс.Ру