TypeScript 泛型限定

admin發表於2019-04-23

泛型比較靈活,可以傳遞多種資料型別,當然也可以對這個傳遞的型別進行限定。

首先看一段程式碼例項:

[typescript] 純文字檢視 複製程式碼
function identity<T>(arg: T): T {
  console.log(arg.length); 
  return arg;
}

上面的程式碼會報錯,泛型可以傳遞多種型別,不一定具有length屬性。

我們可以進行一下限定來解決此問題,也就是要求傳遞的型別必須具有length屬性。

程式碼例項如下:

[typescript] 純文字檢視 複製程式碼
interface Lengthwise {
    length: number;
}
function identity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length); 
  return arg;
}
identity(5)//5是number型別,不具有length屬性
identity("螞蟻部落")//字串具有length屬性

使用extends對泛型新增約束,所以函式傳遞的引數也是有限制的,必須具有length屬性。

[typescript] 純文字檢視 複製程式碼
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"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.

可以宣告一個型別引數,且它被另一個型別引數所約束。

比如,現在想要用屬性名從物件裡獲取這個屬性,要確保這個屬性存在於物件obj上,因此需要在這兩個型別之間使用約束。在TypeScript使用泛型建立工廠函式時,需要引用建構函式的類型別。

程式碼例項如下:

[typescript] 純文字檢視 複製程式碼
function create<T>(c: {new(): T; }): T {
  return new c();
}

再來看一段程式碼例項:

[typescript] 純文字檢視 複製程式碼
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!

使用原型屬性推斷並約束建構函式與類例項的關係。

相關文章