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
相關文章
相關標籤/搜索