TypeScript - 条件类型

你好,未来的 TypeScript 大师们!今天,我们将踏上一段激动人心的旅程,探索 TypeScript 中的条件类型世界。如果你是编程新手,不用担心——我会成为你的友好向导,我们会一步一步地学习。在本课结束时,你会对你学到的东西感到惊讶!

TypeScript - Conditional Types

基本条件类型

让我们从基础开始。TypeScript 中的条件类型就像在代码中做决策一样。想象你在一个冰淇淋店,根据天气热不热来决定选择巧克力还是香草。这基本上就是 TypeScript 中的条件类型所做的!

这里有一个简单的例子:

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

在这段代码中,我们在说:“如果 boolean(代表 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 扩展(或匹配)"Hot",我们选择 "Ice Cream";否则,我们选择 "Hot Chocolate"。

泛型条件类型

现在,让我们升级一下!泛型条件类型允许我们使我们的类型更加灵活和可重用。想象一下,创建一个超级灵活的冰淇淋机,可以根据你放入的东西制作不同的口味。

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(这意味着“这不应该发生”)。

条件类型约束

有时,我们想要对类型进行一些限制。这就像说,“只有在你吃完蔬菜后,你才能吃冰淇淋!”让我们看看这在 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">;  // 错误:类型 '"5"' 不满足约束 'number'。

在这个例子中,NumberOperation 只接受扩展 number 的类型。然后它检查这个数字是否为 0。

在条件类型中推断

最后但同样重要的是,让我们谈谈在条件类型中的推断。这就像拥有一个超级智能的冰淇淋机,可以根据你的心情猜出你想要的口味!

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

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

在这里,Flatten 检查 T 是否是数组。如果是,它推断元素类型 U 并返回它。如果不是,它按原样返回 T

让我们尝试一些更高级的:

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 条件类型世界的第一步。记住,就像学习骑自行车一样,一开始可能会感到摇摇晃晃,但经过练习,你很快就会自如地骑行!

以下是我们在本课中涵盖的方法的快速参考表:

方法 描述
基本条件类型 基于条件进行类型决策
泛型条件类型 创建灵活、可重用的条件类型
条件类型约束 对输入类型进行限制
在条件类型中推断 在条件内提取和推断类型

继续练习,保持好奇心,在你知道之前,你将使用 TypeScript 创造惊人的事物。快乐编码,未来的 TypeScript 大师们!

Credits: Image by storyset