Conditional Types (Условные типы) работают по принципу тернарного оператора: T extends U ? X : Y. Но самое интересное поведение возникает, когда T является Union Type. Это называется Distributive Conditional Types (Распределительные условные типы).
Если проверяемый тип — это «голый» (naked) параметр дженерика, то условие применяется к каждому члену объединения отдельно. Например, (A | B) extends U ? X : Y превращается в (A extends U ? X : Y) | (B extends U ? X : Y). Это поведение лежит в основе таких встроенных утилит, как Exclude и Extract. Понимание дистрибутивности необходимо для фильтрации типов и создания сложной логики вывода типов.
- Модуль 1: Введение в TypeScript
- Модуль 2: Примитивные типы
- Модуль 3: Специальные типы
- Модуль 4: Массивы
- Модуль 5: Кортежи (Tuples)
- Модуль 6: Объекты
- Модуль 7: Функции
- Модуль 8: Union типы
- Модуль 9: Литеральные типы
- Модуль 10: Type Aliases
- Модуль 11: Интерфейсы
- Модуль 12: Type Guards и Narrowing
- Модуль 13: Enums
- Модуль 14: Классы
- Модуль 15: Generics — основы
- Модуль 16: Generics — ограничения
- Модуль 17: Utility Types — базовые
- Модуль 18: Utility Types — работа с Union
- Модуль 19: Utility Types — функции
- Модуль 20: Type Assertions
- Модуль 21: Keyof и Typeof операторы
- Модуль 22: Mapped Types
- Модуль 23: Conditional Types
- Основы Conditional Types.
- Distributive Conditional Types.
- Ключевое слово infer.
- Модуль 24: Discriminated Unions
- Модуль 25: Модули и типы
- Модуль 26: Declaration Files
- Модуль 27: Типизация асинхронного кода
- Модуль 28: Практические паттерны
1. Результат распределения
Рассмотрите условный тип TypeScript, который проверяет, является ли тип строкой. На вход подаётся объединение (union) string | number. Вспомните, как работают дистрибутивные условные типы (Distributive Conditional Types) — они применяют условие к каждому члену union по отдельности, а затем снова объединяют результаты. Проанализируйте код и выберите правильный тип, который получится в результате применения дистрибутивного условного типа.
type IsString<T> = T extends string ? T : never;
type Test = IsString<string | number>;2. Порядок распределения
В этом задании вам нужно восстановить правильную последовательность этапов обработки распределительных условных типов (Distributive Conditional Types) в TypeScript. Перед вами пять текстовых описаний шагов, которые TypeScript выполняет при вычислении условного типа для объединения типов. Эти шаги перепутаны. Расставьте их в логическом порядке, начиная с момента, когда TypeScript встречает условный тип, применённый к объединению, и заканчивая формированием итогового типа.
3. Написание условного типа
Реализуйте условный тип Exclude в TypeScript. Этот встроенный тип исключает из типа T все типы, которые можно присвоить типу U. Вам нужно заполнить пропуски в тернарном операторе, чтобы корректно отфильтровать типы согласно принципу дистрибутивности условных типов. Используйте ключевые слова, которые позволяют типу работать дистрибутивно над объединениями.
type MyExclude<T, U> = T extends U input1S input2S
// Пример использования
// type Result = MyExclude<'a' | 'b' | 'c', 'a' | 'b'>;
// Результат: 'c'4. Поиск распределяемого параметра
Внимательно изучите приведённый код на TypeScript, содержащий несколько условных типов (Conditional Types). Ваша задача — найти и выделить кликом тот единственный дженерик-параметр (символ, расположенный непосредственно слева от ключевого слова `extends` в условии типа), который является 'naked type' и, следовательно, вызовет дистрибутивное поведение условного типа при подстановке юнион-типа. Не отмечайте параметры, которые обёрнуты в массивы, промисы или другие типы, а также не отмечайте сам синтаксис `extends` или другие части кода.
type CheckString = {{T~|~t1}} extends string ? true : false;
type CheckArray = {{T~|~t2}}[] extends string[] ? true : false;
type CheckFunction = (() => {{T~|~t3}}) extends () => string ? true : false;
type CheckPromise = Promise<{{T~|~t4}}> extends Promise ? true : false;
type CheckUnion = {{T~|~t5}} extends U ? true : false; 5. Вычисление Exclude вручную
В TypeScript есть встроенный условный тип Exclude
type A = 'a' | 'b' | 'c';
type B = 'a' | 'c';
type Result = Exclude<A, B>;6. Отключение дистрибутивности
В этом фрагменте кода TypeScript conditional type обернут в квадратные скобки, что отключает дистрибутивность для union-типов. Исправьте определение типа ToArray, убрав квадратные скобки, чтобы conditional type стал дистрибутивным и правильно обрабатывал union-типы.
type ToArray<T> = [T] extends [any] ? T[] : never;type Test = ToArray<string | number>;7. Утилиты и их логика
В левой колонке перечислены названия утилит TypeScript, основанных на дистрибутивных условных типах. В правой колонке — их логические описания, объясняющие поведение этих утилит. Сопоставьте каждую утилиту с соответствующим описанием её работы. Обратите внимание, что в правой колонке нет лишних вариантов, но порядок описаний перемешан.
Exclude<T, U>Extract<T, U>NonNullable<T>ReturnType<T>Parameters<T>InstanceType<T>8. Создание типа Diff
Из предложенных строк соберите определение типа TypeScript `Diff
type Diff<T, U> =T extends U?never:T;U extends TT | U? T : never