通过以上介绍,我们已近大致学习了 function, interface, class, 但是对这些类型做约束时我们都是定死类型的, 比如说, 一个函数的实现是一致的,只是传入类型不同, 我们是不是要定义多个函数类型来承接实现, 这显然是不合理的, 编程所谓的复用一点都没体现出来, 泛型的引入就是为了解决这个问题.
所谓泛型: 就是将类型抽象化,传入参数.
function log<T>(arg: T): T { // T 指的是一个类型, 不是固定的, 可以是任意字符.
return arg;
}
log<number>(1)
log(1) // 可以直接这么写, typeScript会自己推断类型
需要注意的是 上面的 T 泛指任何类型(不同于 any, any 不会进行类型推断), 并且进行类型推断. 如果推断的类型没有代码块的属性或方法, typeScript则会抛出异常.
请看下面的例子:
// 实现一个获取参数长度的方法
function getLen<T>(arg: T): number {
return arg.length // 类型“T”上不存在属性“length”。ts(2339)
}
解决方案是我们可以对泛型参数进行约束,如下:
function getLen<T extends { length: number }>(arg: T): number { // 限制传入的类型必须拥有 length 属性
return arg.length
}
泛型函数我们知道怎么实现了, 我们再来看看泛型接口
- 泛型接口
interface mustLength<T> {
(arg: T): number
}
const fn: mustLength<string> = (arg: string) => arg.length
const fn1: mustLength<number[]> = (arg: number[]) => arg.length
- 泛型类
同泛型接口, 泛型类相对于泛型接口只是定义的关键字换成了 class
class Pub<T> {
subs: T[];
add: (T) => number;
}
let pub = new Pub<Function>()
pub.subs = [];
pub.add = function (p) {
pub.subs.push(p)
return pub.subs.length
};
pub.add(() => console.log(1))
pub.subs.forEach(v => { v() })
网友评论