TypeScript - Условные типы

Здравствуйте, будущие маги TypeScript! Сегодня мы отправимся в увлекательное путешествие в мир Условных типов. Не волнуйтесь, если вы новички в программировании – я буду вашим доброжелательным проводником, и мы будем двигаться шаг за шагом. К концу урока вы будете удивлены, сколько вы узнали!

TypeScript - Conditional Types

Основы Условных типов

Давайте начнем с основ. Условные типы в TypeScript resemble принятие решений в вашем коде. Представьте, что вы вмагазине мороженого и должны решить, выбрать巧克力 или ваниль, в зависимости от того, жаркий ли день или нет. Именно это и делают Условные типы в TypeScript!

Вот простой пример:

type IceCreamChoice = boolean extends true ? "Chocolate" : "Vanilla";

В этом коде мы говорим: "Если boolean (который represents true или false) может быть true, то выберите Chocolate; в противном случае выберите Vanilla."

Но подождите, boolean всегда может быть true, не так ли? Давайте сделаем это более практичным:

type WeatherChoice<T> = T extends "Hot" ? "Ice Cream" : "Hot Chocolate";

let summerChoice: WeatherChoice<"Hot"> = "Ice Cream";
let winterChoice: WeatherChoice<"Cold"> = "Hot Chocolate";

Здесь мы создали тип WeatherChoice, который принимает типовой параметр T. Если T extends (или соответствует) "Hot", мы выбираем "Ice Cream"; в противном случае мы выбираем "Hot Chocolate".

Универсальные Условные типы

Теперь давайте поднимемся на уровень выше! Универсальные Условные типы позволяют сделать наши типы более гибкими и многоразовыми. Представьте себе超级гибкую машину для мороженого, которая может делать разные flavors на основе того, что вы положите.

type IsArray<T> = T extends any[] ? true : false;

type CheckString = IsArray<string>;  // false
type CheckNumberArray = IsArray<number[]>;  // true

В этом примере IsArray - это универсальный тип, который проверяет, является ли вводимый тип T массивом. Если да, то он возвращает true; в противном случае - false.

Давайте попробуем что-то более сложное:

type ElementType<T> = T extends (infer U)[] ? U : never;

type StringArrayElement = ElementType<string[]>;  // string
type NumberArrayElement = ElementType<number[]>;  // number
type NotArrayElement = ElementType<number>;  // never

Здесь ElementType извлекает тип элементов в массиве. Если T является массивом, он выводит элементный тип U. Если T не является массивом, он возвращает never (что означает "эта ситуация не должна произойти").

Ограничения Условных типов

Иногда мы хотим imposingsome ограничения на наши типы. Это как сказать: "Ты можешь есть мороженое, только если съел свои овощи!" Давайте посмотрим, как это работает в TypeScript:

type NumberOperation<T extends number> = T extends 0 ? "Zero" : "Non-zero";

type ZeroCheck = NumberOperation<0>;  // "Zero"
type NonZeroCheck = NumberOperation<5>;  // "Non-zero"
type InvalidCheck = NumberOperation<"5">;  // Error: Type '"5"' does not satisfy the constraint 'number'.

В этом примере NumberOperation принимает только типы, которые extend number. Затем он проверяет, равно ли число 0 или нет.

Вывод типов внутри Условных типов

Последнее, но не менее важное, давайте поговорим о выводе типов внутри условных типов. Это как иметь super-smart машину для мороженого, которая может угадать, какого вкуса мороженое вы хотите, исходя из вашего настроения!

type Flatten<T> = T extends Array<infer U> ? U : T;

type FlattenedNumberArray = Flatten<number[]>;  // number
type FlattenedString = Flatten<string>;  // string

Здесь Flatten проверяет, является ли T массивом. Если да, то он выводит элементный тип U. Если нет, то он возвращает T как есть.

Давайте попробуем что-то более avanzado:

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

function greet(name: string): string {
return `Hello, ${name}!`;
}

type GreetReturn = ReturnType<typeof greet>;  // string

В этом примере ReturnType выводит тип返回имой функции. Он проверяет, является ли T типом функции, и если да, то выводит и возвращает тип返回имой функции R.

Заключение

Поздравляю! Вы только что сделали свои первые шаги в мир Условных типов в TypeScript. Помните, как при обучении езде на велосипеде, сначала это может казаться неустойчивым, но с практикой вы быстро научитесь!

Вот quick reference table методов, которые мы рассмотрели:

Метод Описание
Основы Условных типов Принятие типовых решений на основе условий
Универсальные Условные типы Создание гибких, многоразовых условных типов
Ограничения Условных типов imposingsome ограничения на вводимые типы
Вывод типов внутри Условных типов Извлечение и вывод типов внутри условий

Продолжайте практиковаться, stay curious, и скоро вы начнете создавать удивительные вещи с помощью TypeScript. Удачи в программировании, будущие мастера TypeScript!

Credits: Image by storyset