文章目录
- 泛型
- 形式类型参数
- 实际参数类型
- 泛型约束
- 泛型函数
- 泛型接口
- 泛型别名
泛型
泛型是一种编程风格,它允许在程序中定义形式类型参数,然后在泛型实例化的时候使用实际类型参数来替换形式类型参数。
比如有这样的一个函数:
function identity(arg:): number {
return arg;
}
console.log(identity(90))
identity函数的使用场景是受到限制的,因为它只能接收number类型的值作为参数。要是想让identity函数接受任意的类型值作为参数的话,那么identity函数的参数类型需要设置为any或者是unknown,这样identity函数就能处理number类型或者是any类型的值了。
function identity(arg:): unknown {
return arg;
}
console.log(identity('908'))
但是identity函数中,我们只能了解到参数类型和返回值类型都是任意类型的,而且参数类型和返回值类型是没有任何联系的。
如果我们要知道传入参数的类型,并且将传入参数的类型作为函数返回值类型,这样函数就能够保证参数类型和返回值类型是一直的了。
这就需要引入泛型了,代码如下:
function identity<T>(arg: T): T {
return arg;
}
console.log(identity(89)); // 89
这其中的T是类型参数,它能够捕获函数的参数类型并且作为返回值类型。
在调用泛型函数的时候,是可以为类型参数T传入一个实际类型的,比如:
console.log(identity<number>(90)); // 89
形式类型参数
表示能够绑定到泛型类型或者泛型函数调用的某个实际类型,语法:<TypeParameter, TypeParameter, ...>
,如果有多个形参的话,就使用逗号隔开。
这种风格一般是以大写字母T作为前缀的,比如TResponse:
function identity<TResponse>(arg: TResponse): TResponse {
return arg;
}
console.log(identity<number>(90)); // 89
另一种方式是由字母T开头,并且依次使用后续的U、V等大写字母。如果形参数量比较少的话,使用这种风格比较合适,同时也要注意代码的可读性。
function assign<T, U>(target: T, source: U): T {
return target
}
可以给形参设置默认类型:<T = boolean>
实际参数类型
在使用泛型的时候,传入一个实际类型参数作为形参类型的值,这个过程也叫作泛型的实例化。
identity<number>(90)
泛型约束
可以在形参上定义一个约束条件,限制实际参数类型的范围。语法:<TypeParameter extends ConstraintType>
,TypeParameter 表示形参, extends关键字,ConstraintType一个类型,用来限制TypeParameter的可选类型范围,比如
interface Point {
x: number;
y: number;
}
function move<T extends Point>(x: T): T {
return x;
}
泛型函数
泛型函数是一个函数中带有类型参数的函数。比如:
function f1<T>(x: T): T {
return x;
}
f1<string>('90');
f1<number>(12);
泛型接口
如果接口的定义中带有类型参数,那就是泛型接口,比如:
interface MyArray<T> extends Array<T> {
first: T | undefined;
last: T | undefined;
}
const ar: Array<number> = [9];
const ar1: number[] = [0]
从上面的代码中可以看出,可以使用泛型来声明数组类型的。
泛型别名
泛型别名中定义有类型参数,比如定义一个名为Nullable的别名:
type Nullable<T> = T | undefined | null;
这里面有一个形参类型T,可以表示为空的T类型,就是后面接着的undefined或者null。
这就是泛型简单的介绍!