JS Tower
JavaScript & TypeScriptМодуль 8: Продвинутый TypeScript

Mapped Types

Создание типов на основе других

Цель урока

В этом уроке ты научишься:

  • Создавать mapped types
  • Использовать модификаторы
  • Переименовывать ключи

Базовый синтаксис

type Keys = "a" | "b" | "c";

type Mapped = {
  [K in Keys]: number;
};
// { a: number; b: number; c: number; }

На основе существующего типа

interface User {
  name: string;
  age: number;
  email: string;
}

// Все свойства становятся boolean
type UserFlags = {
  [K in keyof User]: boolean;
};
// { name: boolean; age: boolean; email: boolean; }

Реализация Partial

type MyPartial<T> = {
  [K in keyof T]?: T[K];
};

interface User {
  name: string;
  age: number;
}

type PartialUser = MyPartial<User>;
// { name?: string; age?: number; }

Реализация Readonly

type MyReadonly<T> = {
  readonly [K in keyof T]: T[K];
};

Модификаторы

Добавление (по умолчанию)

type Optional<T> = {
  [K in keyof T]?: T[K];  // добавляет ?
};

type Immutable<T> = {
  readonly [K in keyof T]: T[K];  // добавляет readonly
};

Удаление (-)

type Required<T> = {
  [K in keyof T]-?: T[K];  // удаляет ?
};

type Mutable<T> = {
  -readonly [K in keyof T]: T[K];  // удаляет readonly
};

Переименование ключей (as)

type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface User {
  name: string;
  age: number;
}

type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number; }

Фильтрация ключей

type OnlyStrings<T> = {
  [K in keyof T as T[K] extends string ? K : never]: T[K];
};

interface Mixed {
  name: string;
  age: number;
  email: string;
}

type StringProps = OnlyStrings<Mixed>;
// { name: string; email: string; }

Практические примеры

Nullable версия

type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

interface User {
  name: string;
  age: number;
}

type NullableUser = Nullable<User>;
// { name: string | null; age: number | null; }

Событийные обработчики

type EventHandlers<T> = {
  [K in keyof T as `on${Capitalize<string & K>}Change`]: (value: T[K]) => void;
};

interface Form {
  name: string;
  email: string;
}

type FormHandlers = EventHandlers<Form>;
// { onNameChange: (value: string) => void; onEmailChange: (value: string) => void; }

Практика

Задание 1: Создай Nullable

Задача: Реализуй тип Nullable.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
null

Задание 2: Getters

Задача: Создай тип с геттерами.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Иван

Проверь себя

  1. Что делает keyof?
  2. Как удалить модификатор?
  3. Как переименовать ключи?