阅读 204

TypeScript学习之泛型(2)

泛型类型

实际上可以理解为,将泛型提取出来,作为一个通用类型。
通常,对于泛型函数的类型使用,可能是以下这种方式:(类型变量不一定是T,也可以是其他的名字)

function identity<T>(arg: T): T {     return arg; } let myIdentity: <T>(arg: T) => T = identity; 复制代码

这种写法其实看上去会有点像js中使用箭头函数的形式去声明一个函数。

在TypeScript中,可以将箭头函数部分提取出来,作为一个接口,也就是泛型接口:

interface GenericIdentityFn {     <T>(arg: T): T; } function identity<T>(arg: T): T {     return arg; } let myIdentity: GenericIdentityFn = identity; 复制代码

如果把泛型参数当作整个接口的一个参数,即上述例子中GenericIdentityFn的参数T,这样就能清楚的知道使用的具体是哪个泛型类型,比如说,传入一个number:

interface GenericIdentityFn<T> {     (arg: T): T } function identity<T>(arg: T): T {     return arg; } let myIdentity: GenericIdentityFn<number> = identity; 复制代码

上述例子中,给接口传入了一个参数number,在使用的时候,就意味着使用的时候,这里的泛型类型就是number。

泛型类

除了泛型接口之外,还可以创建泛型类,和泛型接口差不多,泛型类使用<>包裹泛型类型,跟在类名后面。

class GenericNumber<T> (     zeroValue: T;     add: (x: T, y: T) => T ) let mynericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) {     return x + y; } 复制代码

()中是泛型类型的参数列表,对于泛型类型,不一定是number,这也是个传参,同样可以传string等。像接口一样,将泛型类型放在类本身,可以确保类的所有属性都使用想用的类型,保证了类型的统一。

泛型约束

在有些情况下,编译器不能保证每种类型都会有某个属性存在,例如说number类型不存在length属性,但是又会需要去处理,相对于any,限制函数的处理或许是更好的办法。那么,就需要传入的类型中,有这个属性存在,因此,这便对泛型变量T产生了一个约束的概念。

定义一个接口来描述约束条件:

interface Lengthwise {     length: number; } function loggingItentity<T extends Lengthwise>(arg: T): T {     console.log(arg.length);     return arg; } 复制代码

当泛型函数被定义了约束,便不再适用于任意类型。在使用中,必须传入符合约束类型的值:

loggingIdentity(3);  // Error, number doesn't have a .length property loggingIdentity({length: 10, value: 3}) 复制代码

在泛型约束中使用类型参数

可以声明一个类型参数,且它被另一个类型参数所约束。举个例子来说,想从一个对象中获取一个属性,但是又需要确保取到的属性是存在的,这是,可以使用另外一个类型参数来约束这个行为。

function getProperty(obj: T, key: K) {     return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "a"); // okay getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'. 复制代码

在泛型里使用类类型

class BeeKeeper {     hasMask: boolean; } class ZooKeeper {     nametag: string; } class Animal {     numLegs: number; } class Bee extends Animal {     keeper: BeeKeeper; } class Lion extends Animal {     keeper: ZooKeeper; } function createInstance<A extends Animal>(c: new () => A): A {     return new c(); } createInstance(Lion).keeper.nametag;  // typechecks! createInstance(Bee).keeper.hasMask;   // typechecks!


作者:路过的前端小菜鸟
链接:https://juejin.cn/post/7032610487372251150

文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐