Distributive Conditional Types

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

Тренажер по TypeScript

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. Результат распределения

id: 40752_dct_predict_union

Рассмотрите условный тип TypeScript, который проверяет, является ли тип строкой. На вход подаётся объединение (union) string | number. Вспомните, как работают дистрибутивные условные типы (Distributive Conditional Types) — они применяют условие к каждому члену union по отдельности, а затем снова объединяют результаты. Проанализируйте код и выберите правильный тип, который получится в результате применения дистрибутивного условного типа.

Выберите правильный вариант ответа
type IsString<T> = T extends string ? T : never;

type Test = IsString<string | number>;
Сообщения
Проверить
Показать подсказку

2. Порядок распределения

id: 40752_dct_sequencing_logic

В этом задании вам нужно восстановить правильную последовательность этапов обработки распределительных условных типов (Distributive Conditional Types) в TypeScript. Перед вами пять текстовых описаний шагов, которые TypeScript выполняет при вычислении условного типа для объединения типов. Эти шаги перепутаны. Расставьте их в логическом порядке, начиная с момента, когда TypeScript встречает условный тип, применённый к объединению, и заканчивая формированием итогового типа.

Расставьте строки в правильном порядке
TypeScript распределяет (разделяет) объединение T на составляющие типы (например, A и B).
TypeScript начинает обработку условного типа T extends U ? X : Y, где T — это объединение типов (например, A | B).
Условный тип применяется к типу A: проверяется A extends U ? X : Y, получается ResultA.
Результаты применения условного типа к каждому элементу объединяются в новое объединение (например, ResultA | ResultB).
Условный тип применяется к типу B: проверяется B extends U ? X : Y, получается ResultB.
Сообщения
Проверить
Показать подсказку

3. Написание условного типа

id: 40752_dct_replace_ternary

Реализуйте условный тип Exclude в TypeScript. Этот встроенный тип исключает из типа T все типы, которые можно присвоить типу U. Вам нужно заполнить пропуски в тернарном операторе, чтобы корректно отфильтровать типы согласно принципу дистрибутивности условных типов. Используйте ключевые слова, которые позволяют типу работать дистрибутивно над объединениями.

Заполните пропуски
type MyExclude<T, U> = T extends U input1S input2S

// Пример использования
// type Result = MyExclude<'a' | 'b' | 'c', 'a' | 'b'>;
// Результат: 'c'
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

4. Поиск распределяемого параметра

id: 40752_dct_click_target_naked

Внимательно изучите приведённый код на 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 вручную

id: 40752_dct_give_result_exclude

В TypeScript есть встроенный условный тип Exclude, который исключает из типа T все типы, которые можно присвоить типу U. Рассмотрите приведённый код, в котором определены два типа A и B, а затем применяется Exclude. Определите, какой тип будет у результирующего типа Result. Введите ответ в виде строки, соответствующей этому типу (включая кавычки, если тип является строковым литералом).

Что должно получиться?
type A = 'a' | 'b' | 'c';
type B = 'a' | 'c';
type Result = Exclude<A, B>;
Сообщения
Проверить
Показать подсказку

6. Отключение дистрибутивности

id: 40752_dct_error_tuple_disable

В этом фрагменте кода TypeScript conditional type обернут в квадратные скобки, что отключает дистрибутивность для union-типов. Исправьте определение типа ToArray, убрав квадратные скобки, чтобы conditional type стал дистрибутивным и правильно обрабатывал union-типы.

Найдите ошибку и исправьте
type ToArray<T> = [T] extends [any] ? T[] : never;
type Test = ToArray<string | number>;
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

7. Утилиты и их логика

id: 40752_dct_compare_utility

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

Сопоставьте строки в правой(нижней) части с соответствующими строками в левой(верхней) по порядковому номеру
Exclude<T, U>
Extract<T, U>
NonNullable<T>
ReturnType<T>
Parameters<T>
InstanceType<T>
Удаляет из типа T типы, которые можно присвоить U
Получает тип возвращаемого значения функции
Оставляет в T только типы, которые можно присвоить U
Убирает null и undefined из типа T
Получает тип экземпляра класса-конструктора
Получает типы параметров функции в виде кортежа
Сообщения
Проверить
Показать подсказку

8. Создание типа Diff

id: 40752_dct_build_diff

Из предложенных строк соберите определение типа TypeScript `Diff`, который удаляет из объединения типов `T` все типы, присутствующие в объединении `U`. Используйте дистрибутивные условные типы (Distributive Conditional Types) с ключевыми словами `extends`, `?`, `:` и `never`. В решении должны быть использованы только необходимые строки, лишние строки включать не нужно.

Перетяните в правильном порядке строки из одного блока в другой
type Diff<T, U> =
T extends U
?
never
:
T;
U extends T
T | U
? T : never
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

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

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