泛型
泛型可以比喻成一个类型占位符,在使用的时候再去指定类型的一种特性。它是一种抽象的类型,,区别于平时的TS
类型,泛型更像是对类型的编程。
基本使用
假设我们需要一个函数获取传入数组参数的第一项,但是不知道参数和返回值的类型,第一印象会写成下面这样:
typescript
function getFirstIte(arr: any[]): any {
return arr[0];
}
type Person = {
name: string
age: number
}
const person: Person = [{name:"张三",age:"20"}]
getFirstItem(person)
这虽然是符合需求了,但是any
的类型会让TS
丢失类型检查的功能,可以使用泛型动态捕获类型,指定参数和返回值的类型:
typescript
function getFirstItem<T>(arr: T[]): T {
return arr[0];
}
// ...
getFirstItem<Person>(person)
这段代码的意思是:函数接收一个泛型T
,在调用这个函数的时候Person
将会作为T
实际类型传递,会成为参数以及返回值的类型。
函数
三种定义函数的方式均支持使用泛型。
typescript
/* 函数声明 */
function identity<T>(arg: T): T {
return arg;
}
/* 函数表达式 */
const identity = function <T>(arg: T): T {
return arg;
};
/* 箭头函数 */
const identity = <T>(arg: T): T => {
return arg;
};
接口
在接口中使用泛型。
typescript
interface IProps<T>{
name: string
age: T
}
const props: IProps = {
name: "张三",
age: 20
}
type
在类型别名中使用泛型。
typescript
type Params<T> = T;
默认值
给泛型一个默认值,如果泛型不传参,它会使用默认值,可以完全类比于函数的默认参数来理解。
typescript
function identity<T = string>(arg: T): T {
return arg;
}
identity("abc") // T: string
还可以对类型进行约束,表示传入的类型必须是某个类型的子类或包含某个属性:
typescript
function getLength<T extends { length: number }>(arg: T): T {
return arg.length;
}
getLength("abc") // OK,string 包含 length 属性,静态检查过关
getLength(123) // Error,number 不包含 length 属性,TS 检查错误
类
类结合泛型使用,可以给类的属性/方法在实例化时添加类型,需要注意的是,类的静态属性/方法不能使用泛型类型。
typescript
class GenericNumber<T> {
zeroValue: T
add: (x: T, y: T) => T
}
const myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function (x, y) {
return x + y
}