ts-泛型

1、泛型类型

首先先了解泛性函数

\\ 普通方法
function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: <T>(arg: T) => T = identity;

\\对象字面量的方法写函数

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: {<T>(arg: T): T} = identity;// {<T>(arg: T): T}  ===  <T>(arg: T) => T

第一个泛型接口

interface GenericIdentityFn<T> {
    (arg: T): T;
}

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn<number> = identity;

或者

interface GenericIdentityFn {
    <T>(arg: T): T;
}

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn = identity;

2、泛型类

看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };

console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));

3、泛型约束

看一个想访问arglength属性,但是编译器并不能证明每种类型都有length属性,所以就报错的例子

function loggingIdentity<T>(arg: T): T {
    console.log(arg.length);  // Error: T doesn't have .length
    return arg;
}

为此,我们定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

//现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3);  // Error, number doesn't have a .length property
//我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});

4、在泛型约束中使用类型参数 === 官方不够语义化,其实就是泛型的入参也拥有类似函数入参的特性,参数之间可以互相约束


\\多个不同的泛型入参之间设置约束关系,如下代码所示:
interface ObjSetter {
  <O extends {}, K extends keyof O, V extends O[K]>(obj: O, key: K, value: V): V;
}

const setValueOfObj: ObjSetter = (obj, key, value) => (obj[key] = value);
setValueOfObj({ id: 1, name: 'name' }, 'id', 2);
setValueOfObj({ id: 1, name: 'name' }, 'name', 'newName');
setValueOfObj({ id: 1, name: 'name' }, 'age', 2);
setValueOfObj({ id: 1, name: 'name' }, 'id', '2');

\\泛型入参与函数入参还有一个相似的地方在于,它也可以给泛型入参指定默认值(默认类型)
interface ReduxModelSpecified<State extends { id: number; name: string }> {
  state: State
}
interface ReduxModelSpecified2<State = { id: number; name: string }> {
  state: State
}
type ComputedReduxModel5 = ReduxModelSpecified2;
type ComputedReduxModel6 = ReduxModelSpecified2<{ id: number; name: string; }>;
type ComputedReduxModel7 = ReduxModelSpecified; // ts(2314) 缺少一个类型参数

5、在泛型里使用类类型===语义化就是:函数传入类,实现函数的时候实例化这个类

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!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值