Полное руководство по условным типам в TypeScript

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

  1. Базовый условный тип:
    Условные типы позволяют нам определять типы на основе определенных условий. Вот базовый пример, демонстрирующий использование условных типов:
type Check<T> = T extends string ? boolean : number;
const result1: Check<string> = true; // Valid
const result2: Check<number> = 10; // Valid
const result3: Check<boolean> = false; // Error

В этом примере тип Checkоценивается как boolean, если тип ввода Tравен string, и до numberв противном случае.

  1. Условный вывод типа.
    Условные типы также можно использовать для вывода типов на основе условий. Рассмотрим следующий пример:
type InferType<T> = T extends Array<infer U> ? U : T;
type Result1 = InferType<string[]>; // Result1 will be 'string'
type Result2 = InferType<number[]>; // Result2 will be 'number'
type Result3 = InferType<boolean>; // Result3 will be 'boolean'

В этом случае тип InferTypeвыводит тип элемента массива, если входной тип является массивом, и возвращает сам входной тип в противном случае.

  1. Дистрибутивные условные типы:
    Дистрибутивные условные типы распределяются по типам объединения. Это может быть полезно во многих сценариях. Вот пример:
type Flatten<T> = T extends any[] ? T[number] : T;
type Result1 = Flatten<string>; // Result1 will be 'string'
type Result2 = Flatten<string[]>; // Result2 will be 'string'
type Result3 = Flatten<string | number>; // Result3 will be 'string | number'

В этом примере тип Flattenвыравнивает тип массива до его типа элемента и сохраняет типы, не являющиеся массивами, неизменными.

  1. Расширенное использование.
    Условные типы также можно комбинировать с другими функциями TypeScript, такими как сопоставленные типы и переназначение клавиш. Вот расширенный пример:
type MapKeys<T, U> = {
  [K in keyof T]: K extends keyof U ? U[K] : never;
};
type Input = { a: string; b: number; c: boolean };
type Mapping = { a: number; b: boolean };
type Result = MapKeys<Input, Mapping>;
// Result will be { a: number, b: boolean, c: never }

В этом примере тип MapKeysсопоставляет ключи Tна основе ключей U. Если ключ в Tсуществует в U, назначается соответствующий тип значения; в противном случае ему присваивается never.

Условные типы — это мощная функция TypeScript, которая позволяет нам определять типы на основе условий и выполнять преобразования типов. В этой статье мы рассмотрели несколько методов использования условных типов на примерах кода. Используя условные типы, разработчики могут создавать более выразительные и точные определения типов в своих проектах TypeScript.