Что такое Mapped Types

Ответ

Mapped Types в TypeScript позволяют создавать новые типы на основе существующих, применяя преобразования к каждому свойству исходного типа. Они используют синтаксис [K in keyof T] для итерации по ключам типа.

Пример:

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

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

type ReadonlyPerson = Readonly<Person>;
// Эквивалентно:
// {
//     readonly name: string;
//     readonly age: number;
// }

Также можно добавлять модификаторы (+, -) и фильтровать свойства:

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

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

Встроенные mapped types: Partial, Required, Readonly, Pick, Record.

Ответ 18+ 🔞

Да ты посмотри, что эти умники в TypeScript придумали! Mapped Types, блядь. Ну это ж просто магия какая-то, а не фича. Сидишь такой, ковыряешь в носу, а потом — бац! — и создаёшь новые типы из старых, как из говна конфетку.

Вот смотри, как это работает, ёпта. Берёшь старый тип и начинаешь каждый его ключик, как барана на бойне, перебирать. Синтаксис вот этот вот: [K in keyof T]. Это как сказать: «А ну-ка, сука, все свойства по струнке становись, сейчас мы вас тут преобразуем!»

Вот, например, классика жанра — сделать всё readonly, чтобы никто твои данные не трогал своими грязными лапами:

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

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

type ReadonlyPerson = Readonly<Person>;
// Получается вот такая хуйня:
// {
//     readonly name: string;
//     readonly age: number;
// }

Теперь этот Person — неприкосновенная святыня, блядь. Захотел поменять name? Получи в ебало ошибку компиляции, распиздяй!

А ещё можно с модификаторами играться, как кот с мышкой. Хочешь — все свойства сделаешь опциональными, поставив вопросик. А захочешь — наоборот, вырвешь этот вопросик с корнем, сделав всё обязательным! Вот, полюбуйся на это безобразие:

type Optional<T> = {
    [K in keyof T]?: T[K]; // Всё можно, а можно и не можно
};

type Required<T> = {
    [K in keyof T]-?: T[K]; // Обязательно, сука! Никаких «может быть»!
};

Это ж, блядь, чистой воды волшебство! Минусик перед вопросиком — и опциональность к ебеням улетела!

И самое охуительное — что тебе даже выдумывать ничего не надо. У них там уже целый арсенал встроенных mapped types приготовлен: Partial, Required, Readonly, Pick, Record. Бери и пользуйся, как будто так и надо!

В общем, штука мощная. Прям чувствуется, что дядьки, которые это придумали, знали, где собака зарыта. А зарыта она, блядь, в гибкости типизации и отсутствии головной боли на ровном месте.