TypeScript 中的泛型
什么是泛型
泛型(Generic Types)即多种类型。允许开发者在编写函数或类时,不预先确定具体的数据类型,而是使用类型参数来表示。例如,一个简单的泛型函数可以这样定义:
typescript
type F<A, B> = A | B
type Result = F<string, number>
// string | number
泛型的语法
type F<A, B> = A | B
type Result = F<string, number>
F:函数明
A,B:参数列表
A | B:函数体/返回值
Result:返回一个类型
F<string, number>:函数调用
泛型的本质
函数的本质是什么?
推后执行的、部分待定的代码
javascript
console.log(1) // 立即执行
const f1 = () => console.log(1) // 这是定义了,还没执行,这就是推后执行
const f2 = (x) => console.log(x) // x 就是部分待定的代码,f2(1) 传入1代码执行
而泛型,则是推后执行的、部分待定的类型
为什么需要泛型
因为没有泛型,有点功能做不了
例如:
typescript
function echo(whatever: number | string | boolean) {
return whatever
}
参数类型和返回值类型也许不一致
我们希望传入什么类型,返回什么类型。传入 number 返回 number,传入 string 返回 string,传入 boolean 返回 boolean,但现阶段做不到这种精细化的类型区分,所以必须使用泛型
结论
没有泛型,有些奇怪的需求就无法实现
没有泛型的类型系统,就如同没有函数的编程语言
难度为一星的泛型
并集、交集、interface
代入法和默认参数
typescript
type Union<A, B> = A | B
type Union3<A, B, C> =A | B | C
type Intersect<A, B> =A & B
type Intersect3<A, B, C> =A & B & C
interface List<A> {
[index:number]: A
}
interface Hash<V> {
[key:string]: V
}
在泛型中使用 extends(难度为二星的泛型)
typescript
type Person = { name: string }
type LikeString<T> = ???
type LikeNumber<T> = ???
type LikePerson<T> = ???
type R1 = LikeString<'h1'> // true
type R2 = LikeString<true> // false
type S1 = LikeNumber<666> // 1
type S2 = LikeNumber<false> // 2
type T1 = LikePerson<{ name: 'frank', xxx: 1}> // yes
type T2 = LikePerson<{ xxx: 1}> // no
type LikeString<T> = T extends string ? true : false
type LikeNumber<T> = T extends number ? 1 : 2
type LikePerson<T> = T extends Person ? 'yes' : 'no'
extends 读作 继承 或 包含于
这个叫做 Conditional Type:条件类型
规则
- 若 T 为 never,则表达式的值为 never
- 若 T 为联合类型,则分开计算
泛型约束
typescript
type GetKeyType<T, K extends keyof T> = T[K]
分配率
泛型是指在定义函数、接口或类时,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
应用场景:当我们需要考虑代码的可复用性时,就需要用到泛型。让组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型。泛型允许同一个函数接受不同类型参数,相比于使用 Any 类型,使用泛型来创建的组件可复用和易扩展性要更好,因为泛型会保留参数类型。
泛型可用于接口、类、变量
泛型接口
typescript
interface identityFn<T> {
(arg: T): T;
}
泛型类
typescript
class GenericNumber<T> {
zeroValue: T;
add:(x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
return x + y
}
泛型变量
使用大写字母A-Z定义的类型变量都属于泛型,常见的泛型变量如下:
- T(Type):表示一个 TypeScript 类型
- K(Key):表示对象中的键类型
- V(Value):表示对象中的值类型
- E(Element):表示元素类型