当前位置:  首页>> 技术小册>> TypeScript入门指南

TypeScript是一种静态类型的编程语言,它提供了一些高级类型工具,如条件类型和infer关键字,使得类型系统更加灵活和强大。本章节将重点介绍条件类型和infer关键字在TypeScript中的使用,并通过代码示例演示它们的具体应用。


1、条件类型

条件类型是一种可以根据类型关系条件性地选择另一种类型的工具。它通常用于泛型类型的约束,以根据泛型类型的具体类型参数来选择不同的类型。

基本语法
条件类型的基本语法如下:

  1. T extends U ? X : Y

其中,T和U是两种类型,X和Y是两种备选类型。当T可以赋值给U时,条件类型的值为X,否则为Y。

示例
我们来看一个简单的例子,实现一个泛型函数trim,将字符串去除两端的空格。如果参数是字符串类型,则直接调用trim()方法;如果是其他类型,则返回原值。

  1. type IsString<T> = T extends string ? true : false;
  2. function trim<T extends string | number>(value: T): IsString<T> extends true ? string : T {
  3. return typeof value === 'string' ? value.trim() : value;
  4. }
  5. console.log(trim(' hello ')); // 'hello'
  6. console.log(trim(123)); // 123

在上面的代码中,我们定义了一个条件类型IsString,它用于判断类型T是否是字符串类型。如果T是字符串类型,则条件类型的值为true,否则为false。

在trim函数中,我们使用了泛型类型T extends string | number来约束参数的类型。接着使用了条件类型,当IsString为true时,返回string类型的结果;否则返回T类型的结果。这样,我们就实现了一个能够处理字符串和其他类型的函数。

嵌套条件类型

条件类型可以进行嵌套,以实现更加复杂的类型逻辑。

  1. type NonNullable<T> = T extends null | undefined ? never : T;
  2. type Flatten<T> = T extends Array<infer U> ? Flatten<U> : T;
  3. type MyType = { a?: number[], b: string } | null;
  4. type MyTypeWithoutNull = NonNullable<MyType>;
  5. type MyTypeFlatten = Flatten<MyType>;
  6. // MyTypeWithoutNull 的类型为 { a?: number[], b: string }
  7. // MyTypeFlatten 的类型为 number | string

在上面的例子中,我们定义了两个条件类型。NonNullable用于判断类型T是否为null或undefined类型,如果是,则返回never类型,否则返回T本身。Flatten用于将嵌套的数组类型展开成一维数组。在定义Flatten时,我们使用了infer关键字,它表示要推断的类型,用于获取数组元素的类型。

我们还定义了一个复杂的类型MyType,它可以是一个MyType类型为{ a?: number[], b: string }或null类型。我们使用NonNullable来移除null类型,得到{ a?: number[], b: string }类型。接着使用Flatten来展开数组类型,得到number | string类型。这样,我们就可以通过条件类型和嵌套类型的组合,处理更加复杂的类型逻辑。

2、infer关键字

infer是TypeScript 2.8版本中引入的一个新关键字,用于推断类型变量的类型。它通常用于条件类型的右侧,以获取泛型类型的具体类型参数。

基本语法
infer的基本语法如下:

  1. T extends (infer U)[] ? U : never

其中,T extends (infer U)[]表示T是一个数组类型,并将数组元素类型赋值给类型变量U。U即为要推断的类型变量,可以在条件类型的其他地方使用。如果T不是数组类型,则返回never类型。

示例
我们来看一个示例,实现一个泛型函数head,返回数组的第一个元素。我们使用infer关键字来获取数组元素的类型。

  1. function head<T extends any[]>(arr: T): T extends [infer U, ...any[]] ? U : never {
  2. return arr[0];
  3. }
  4. const arr1 = [1, 2, 3];
  5. const arr2 = ['a', 'b', 'c'];
  6. const arr3 = [];
  7. console.log(head(arr1)); // 1
  8. console.log(head(arr2)); // 'a'
  9. console.log(head(arr3)); // never

在上面的代码中,我们使用泛型类型T extends any[]来约束参数的类型,表示参数必须是一个数组类型。接着使用条件类型T extends [infer U, …any[]] ? U : never,表示当T是一个非空数组类型时,返回数组第一个元素的类型;否则返回never类型。在条件类型中,我们使用了infer关键字来获取数组元素的类型。

通过上面的示例,我们可以看到,infer关键字可以方便地获取泛型类型的具体类型参数,使得类型系统更加灵活和强大。

小结
本文介绍了TypeScript中的条件类型和infer关键字,以及它们的基本语法和应用场景。通过使用这些高级类型工具,我们可以更加方便地实现复杂的类型逻辑,提高代码的可读性和可维护性。


该分类下的相关小册推荐: