JavaScript & TypeScriptМодуль 8: Продвинутый TypeScript
Conditional Types
Условные типы в TypeScript
Цель урока
В этом уроке ты научишься:
- Создавать условные типы
- Использовать infer
- Применять распределение
Базовый синтаксис
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
type C = IsString<"hello">; // trueПрактические примеры
// Извлечение типа элемента массива
type ElementType<T> = T extends (infer E)[] ? E : never;
type A = ElementType<string[]>; // string
type B = ElementType<number[]>; // number
type C = ElementType<string>; // never
// Извлечение типа возврата
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = () => string;
type R = MyReturnType<Fn>; // stringinfer
Выводит тип внутри условия:
// Тип первого параметра
type FirstParam<T> = T extends (first: infer F, ...args: any[]) => any
? F
: never;
type Fn = (name: string, age: number) => void;
type First = FirstParam<Fn>; // string
// Тип промиса
type Unpacked<T> = T extends Promise<infer U> ? U : T;
type A = Unpacked<Promise<string>>; // string
type B = Unpacked<number>; // numberРаспределение (Distribution)
Условный тип распределяется по union:
type ToArray<T> = T extends any ? T[] : never;
type A = ToArray<string | number>;
// string[] | number[]
// Отключение распределения
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
type B = ToArrayNonDist<string | number>;
// (string | number)[]Встроенные условные типы
// Exclude — исключить из union
type Exclude<T, U> = T extends U ? never : T;
type A = Exclude<"a" | "b" | "c", "a">;
// "b" | "c"
// Extract — извлечь из union
type Extract<T, U> = T extends U ? T : never;
type B = Extract<"a" | "b" | "c", "a" | "d">;
// "a"
// NonNullable
type NonNullable<T> = T extends null | undefined ? never : T;Сложные примеры
Глубокий Partial
type DeepPartial<T> = T extends object
? { [K in keyof T]?: DeepPartial<T[K]> }
: T;
interface User {
name: string;
address: {
city: string;
zip: string;
};
}
type PartialUser = DeepPartial<User>;
// Все свойства опциональны, включая вложенныеИзвлечение ключей по типу значения
type KeysOfType<T, V> = {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T];
interface User {
name: string;
age: number;
email: string;
}
type StringKeys = KeysOfType<User, string>;
// "name" | "email"Практика
Задание 1: IsArray
Задача: Создай тип IsArray.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
true false
Задание 2: Unpacked
Задача: Извлеки тип из Promise или массива.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
string number
Задание 3: Exclude
Задача: Реализуй свой Exclude.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
b c
Проверь себя
- Что делает infer?
- Как работает распределение?
- Как отключить распределение?