軟件工程主要部分就是構(gòu)建不僅良好定義喂江,通用的而且可復(fù)用APIs。
type variable
能確定傳入?yún)?shù)的類型也能用也能用來表示返回的類型
function identity<T>(arg: T): T {
return arg;
}
上面的就叫做Generics
旁振,它允許我們在函數(shù)的一側(cè)導(dǎo)入Type information
获询,然后在另一側(cè)輸出這個Type information
泛型函數(shù)調(diào)用
- 顯示傳入類型參數(shù)
let output = identity<string>("myString"); // type of output will be 'string'
- 通過TypeScript的
type infer
自動幫我們判斷并設(shè)置Type T
let output = identity("myString"); // type of output will be 'string'
- 在更復(fù)雜的用法中,可能需要顯示的傳入類型參數(shù)
泛型類型Generic Types
為了表示一下泛型函數(shù)的類型:
function identity<T>(arg: T): T {
return arg;
}
我們可以定義一下幾種方式:
- 直接寫成函數(shù)類型
let myIdentity: <T>(arg: T) => T = identity;
T的命名方式隨意拐袜,只要數(shù)量和和使用方式相同就
let myIdentity: <U>(arg: U) => U = identity;
- 寫在對象字面量的
call signature
里面
let myIdentity: {<T>(arg: T): T} = identity;
- 寫在
Interface
里面吉嚣,定義generic interface
interface GenericIdentityFn {
<T>(arg: T): T;
}
let myIdentity: GenericIdentityFn = identity;
我們也可以創(chuàng)建Generic class,但是不能創(chuàng)建Generic enums 和 Generic namespaces
Generic Constraints
- 我們想要創(chuàng)建一個能處理類型集的泛型函數(shù)蹬铺,而且我們知道這個類型集有哪些方法尝哆,能做什么。那么我們就需要對泛型做一些限制來保證這些類型集的方法可用甜攀。
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;
}
- 在泛型約束中使用類型參數(shù)
如果兩個泛型參數(shù)琐馆,一個參數(shù)需要受到另外一個參數(shù)的約束。
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'.
- 在泛型中使用
class types
- 用構(gòu)造函數(shù)來引用類的類型
function create<T>(c: {new(): T; }): T {
return new c();
}
- 使用原型屬性來推斷和限制類類型的
constructor side
和instance side
的關(guān)系
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!