Quickly Uderstand TypeScript Generics

速通了解 TypeScript 泛型

前言

对于 TypeScript 的泛型🔗 我一直有种恐惧,什么满满的 <T><U>extends、多层嵌套,看起来就很可怕。毕竟在日常开发里,好像也不太需要……对吧?的确解决小问题如此,但在特定问题下泛型将会非常必要。

什么原因需要有泛型存在?

通常在规划可重复运用的代码片段时会需要泛型,具体来说:

  • 某个类型要进行转换(Utility Types🔗
  • 某个函数要接受不同数据类型的输入……
  • 某个组件要接受不同数据类型的输入……(Vue Generic🔗

泛型本身很简单

泛型 = 类型版本的参数

相较于赋予函数参数具体类型过于死板:

function print(message: string): string {
return message
}
print('hi')
print(123) // Argument of type 'number' is not assignable to parameter of type 'string'

通过泛型使定义的类型更具弹性并可重复利用:

function print<MessageType>(message: MessageType): MessageType {
return message
}
print('hi') // function print<"hi">(message: "hi"): "hi"
print(123) // function print<123>(message: 123): 123

可想象 <MessageType> 泛型类型相当于通过 message 推断而生。

extends - 泛型限制

通过关键字 extends 缩限泛型的可能性:

function print<MessageType extends string | number>(message: MessageType): MessageType {
return message
}
print('hi')
print(123)
print(false) // Argument of type 'boolean' is not assignable to parameter of type 'string | number'.

相较于「名词(A 是 string)」更类似「形容词(A 拥有 stringnumber 特性)」。

Conditional types - 条件类型

使用类似JavaScript 条件运算子的语法基于 extends 的判断可以转换出不同的类型:

type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false

总结

学习泛型可用于打造更泛用的类型与程序

每次看到多层嵌套复杂的条件类型,都认真尊敬生产等级的 TypeScript 库需要大量的心力维护和安排。

延伸阅读