TypeScript基础入门 - 泛型 - 泛型约束

转载node

TypeScript基础入门 - 泛型 - 泛型约束

项目实践仓库git

https://github.com/durban89/typescript_demo.git
tag: 1.3.4

为了保证后面的学习演示须要安装下ts-node,这样后面的每一个操做都能直接运行看到输出的结果。github

npm install -D ts-node

后面本身在练习的时候能够这样使用typescript

npx ts-node 脚本路径

泛型

泛型约束

我以前分享的一个例子中,有时候想操做某类型的一组值,而且知道这组值具备什么样的属性。在loggingIdentity例子中,咱们想访问arg的length属性,可是编译器并不能证实每种类型都有length属性,因此就报错了。npm

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


相比于操做any全部类型,咱们想要限制函数去处理任意带有.length属性的全部类型。 只要传入的类型有这个属性,咱们就容许,就是说至少包含这一属性。 为此,咱们须要列出对于T的约束要求。为此,咱们定义一个接口来描述约束条件。 建立一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束:函数

interface LengthDefine {
    length: number;
}

function loggingIdentity<T extends LengthDefine>(arg: T): T {
    console.log(arg.length);

    return arg;
}


如今这个泛型函数被定义了约束,所以它再也不是适用于任意类型:学习

loggingIdentity(3);


运行后会遇到以下错误提示spa

⨯ Unable to compile TypeScript:
src/generics_5.ts(11,17): error TS2345: Argument of type '3' is not assignable to parameter of type 'LengthDefine'.


咱们须要传入符合约束类型的值,必须包含必须的属性:code

loggingIdentity({length: 10, value:3});

运行后会获得以下结果对象

$ npx ts-node src/generics_5.ts
10

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

咱们能够声明一个类型参数,且它被另外一个类型参数所约束。 好比,如今咱们想要用属性名从对象里获取这个属性。 而且咱们想要确保这个属性存在于对象 obj上,所以咱们须要在这两个类型之间使用约束。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key]
}

let x = {a:1, b:2, c:3, d:4};
getProperty(x, "a"); // 正常
getProperty(x, "m"); // 异常

运行后获得以下错误信息

$ npx ts-node src/generics_5.ts
⨯ Unable to compile TypeScript:
src/generics_5.ts(21,16): error TS2345: Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.

在泛型里使用类类型

在TypeScript使用泛型建立工厂函数时,须要引用构造函数的类类型。好比,

function create<T> (c: {new(): T;}): T {
    return new c();
}

一个更高级的例子,使用原型属性推断并约束构造函数与类实例的关系。

class Keeper1 {
    hasMask: boolean;
}

class Keeper2 {
    nameTag: string;
}

class Keeper3 {
    numLength: number;
}

class ChildrenKeeper1 extends Keeper3 {
    keeper: Keeper1;
}


class ChildrenKeeper2 extends Keeper3 {
    keeper: Keeper2;
}

function createInstance<A extends Keeper3> (c: new() => A): A {
    return new c();
}

console.log(createInstance(ChildrenKeeper1));
console.log(createInstance(ChildrenKeeper2));

运行后获得以下输出

$ npx ts-node src/generics_5.ts
ChildrenKeeper1 {}
ChildrenKeeper2 {}


感受没在实际应用中使用,很鸡肋呀

本实例结束实践项目地址

https://github.com/durban89/typescript_demo.git
tag: 1.3.5
相关文章
相关标签/搜索