轉載node
項目實踐倉庫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