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