Условные типы TypeScript
Условные типы в TypeScript предоставляют способ создания типов, зависящих от условия. Они обеспечивают большую гибкость и выразительность в определениях типов, позволяя моделировать сложные отношения типов в ясной и лаконичной манере. В этой статье рассматривается, как условные типы работают в TypeScript, и приводятся примеры, иллюстрирующие их использование.
Что такое условные типы?
Условные типы позволяют создавать типы, которые выбираются на основе условия. Они похожи на условные операторы в программировании, но работают на уровне типа. Базовый синтаксис условного типа:
type ConditionalType = T extends U ? X : Y;
В этом синтаксисе:
T
— проверяемый тип.Тип для сравнения — U
.X
— тип, возвращаемый, еслиT
расширяетU
.Y
— тип, возвращаемый, еслиT
не расширяетU
.
Базовый пример условных типов
Вот простой пример условного типа, который возвращает различные типы в зависимости от того, является ли данный тип строкой или нет:
type IsString = T extends string ? "String" : "Not a string";
type Result1 = IsString; // Result1 is "String"
type Result2 = IsString; // Result2 is "Not a string"
В этом примере IsString
проверяет, расширяет ли T
string
. Если да, то результатом будет "String"
; в противном случае результатом будет "Not a string"
.
Использование условных типов с универсальными типами
Условные типы также могут использоваться с универсальными типами для создания более гибких и повторно используемых определений типов. Например, тип, который извлекает возвращаемый тип функции:
type ReturnType = T extends (...args: any[]) => infer R ? R : never;
type FunctionType = (x: number) => string;
type Result = ReturnType; // Result is string
В этом примере ReturnType
использует ключевое слово infer
для вывода типа возвращаемого значения R
типа функции T
. Если T
является типом функции, ReturnType
будет типом возвращаемого значения; в противном случае по умолчанию используется never
.
Условные типы с типами объединения
Условные типы также могут работать с типами union для обработки нескольких возможных типов. Например, различая разных членов union:
type ExtractString = T extends string ? T : never;
type UnionType = string | number | boolean;
type Result = ExtractString; // Result is string
В этом примере ExtractString
извлекает string
из типа объединения UnionType
, в результате чего получается string
.
Условные типы с сопоставлением типов
Условные типы можно комбинировать с отображениями типов для создания более сложных преобразований типов. Например, отображение массива типов для применения условного типа:
type MapArray = {
[K in keyof T]: T[K] extends string ? T[K] : never;
};
type ArrayType = [string, number, boolean];
type MappedArray = MapArray; // MappedArray is [string, never, never]
В этом примере MapArray
сопоставляет каждый элемент массива T
и применяет условный тип к каждому элементу, в результате чего получается массив, в котором сохраняются только строковые элементы.
Заключение
Условные типы в TypeScript — это мощный инструмент для создания гибких и выразительных определений типов. Используя условные типы, разработчики могут моделировать сложные отношения типов, обрабатывать различные сценарии и повышать безопасность типов в своем коде TypeScript. Понимание того, как эффективно использовать условные типы, может значительно повысить способность писать надежный и поддерживаемый код TypeScript.