Typy warunkowe TypeScript

Typy warunkowe w TypeScript umożliwiają tworzenie typów zależnych od warunku. Umożliwiają one większą elastyczność i ekspresywność w definicjach typów, umożliwiając modelowanie złożonych relacji między typami w sposób przejrzysty i zwięzły. W tym artykule omówiono, jak działają typy warunkowe w TypeScript, i podano przykłady ilustrujące ich zastosowanie.

Czym są typy warunkowe?

Typy warunkowe umożliwiają tworzenie typów wybieranych na podstawie warunku. Są podobne do instrukcji warunkowych w programowaniu, ale działają na poziomie typu. Podstawowa składnia typu warunkowego jest następująca:

type ConditionalType = T extends U ? X : Y;

W tej składni:

  • T to sprawdzany typ.
  • U to typ, z którym należy porównywać.
  • X to typ zwracany, jeżeli T rozszerza U.
  • Y to typ zwracany, jeśli T nie rozszerza U.

Podstawowy przykład typów warunkowych

Oto prosty przykład typu warunkowego, który zwraca różne typy w zależności od tego, czy dany typ jest ciągiem znaków, czy nie:

type IsString = T extends string ? "String" : "Not a string";

type Result1 = IsString;  // Result1 is "String"
type Result2 = IsString;  // Result2 is "Not a string"

W tym przykładzie IsString sprawdza, czy T rozszerza string. Jeśli tak, wynikiem jest "String"; w przeciwnym razie jest to "Not a string".

Używanie typów warunkowych z typami generycznymi

Typy warunkowe mogą być również używane z typami generycznymi, aby tworzyć bardziej elastyczne i wielokrotnego użytku definicje typów. Na przykład typ, który wyodrębnia typ zwracany przez funkcję:

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

type FunctionType = (x: number) => string;

type Result = ReturnType;  // Result is string

W tym przykładzie ReturnType używa słowa kluczowego infer w celu wywnioskowania typu zwracanego R typu funkcji T. Jeśli T jest typem funkcji, typem zwracanym będzie ReturnType; w przeciwnym razie wartością domyślną jest never.

Typy warunkowe z typami unii

Typy warunkowe mogą również współpracować z typami union, aby obsługiwać wiele możliwych typów. Na przykład rozróżnianie różnych członków union:

type ExtractString = T extends string ? T : never;

type UnionType = string | number | boolean;

type Result = ExtractString;  // Result is string

W tym przykładzie ExtractString wyodrębnia string z typu unii UnionType, co daje w wyniku string.

Typy warunkowe z mapowaniami typów

Typy warunkowe można łączyć z mapowaniami typów, aby tworzyć bardziej złożone transformacje typów. Na przykład mapowanie na tablicy typów w celu zastosowania typu warunkowego:

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]

W tym przykładzie MapArray mapuje każdy element tablicy T i stosuje typ warunkowy do każdego elementu, co skutkuje powstaniem tablicy, w której zachowywane są tylko elementy ciągu.

Wniosek

Typy warunkowe w TypeScript to potężne narzędzie do tworzenia elastycznych i ekspresyjnych definicji typów. Wykorzystując typy warunkowe, programiści mogą modelować złożone relacje typów, obsługiwać różne scenariusze i poprawiać bezpieczeństwo typów w swoim kodzie TypeScript. Zrozumienie, jak skutecznie używać typów warunkowych, może znacznie zwiększyć zdolność pisania solidnego i łatwego w utrzymaniu kodu TypeScript.