介紹
???? 在軟件工程中碍遍,我們不僅要創(chuàng)建一致的定義良好的API奖磁,同時也要考慮可重用性改基,泛型,可以用來提高代碼的重用性。在代碼中秕狰,我們不僅需要支持當(dāng)前設(shè)計的數(shù)據(jù)類型稠腊,同時也要支持將來的數(shù)據(jù)類型,泛型鸣哀,提供了這種方便架忌。
泛型-初探
- 不使用泛型
function identity(arg: number): number { return arg; }
// 或者
function identity(arg: any): any { return arg; }
- 使用泛型定義
function identity<T>(arg: T): T { return ard; }
// 這樣我們使用的時候就很方便:
let outputStr: string = identity<string>('myString'); // 這里 `T` 明確了是 `string`類型
let outputNum: number = identity<number>(123); // 這里 `T` 明確了是 `number`類型
- 方法中使用泛型的擴(kuò)展
function loggingIdentiry<T>(arg: Array<T>): Array<T>{ return arg; }
泛型接口
interface Resource<T>{
limit: number;
offset: number;
size: number;
items: Array<T>;
}
interface GenericIdentityFn<T>{
(arg: T): T;
}
泛型類
class GenericNumber<U>{
zeroValue: U;
add: (x: U, y: U) => U;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; }
泛型約束 extends
有時候我們需要確定某一類型一定具有某個屬性,可以通過extends
實現(xiàn)
interface Lengthwise {
length: number;
}
function loggingIndetity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 如果沒有`extends Lengthwise`的話我衬,這里使用length編譯的時候就會報錯
return arg;
}
// 因為使用了約束叹放,所以arg已經(jīng)不是任意類型了,而是需要包含`length`屬性的任意類型
loggingIdentity(3); // Error挠羔,number doesn't have a .length property 就會報錯了井仰。
loggingIdentity({ length: 10, value: 3 }); // ? 這樣就是爭取的使用方式了
在泛型約束中使用類型參數(shù)
聲明一個類型參數(shù),且它被另一個類型參數(shù)所約束破加,如 想要屬性名從對象里獲取這個屬性俱恶,并且確保這個實行存在于對象obj
上,因此需要在這兩個類型之間使用約束
function getProperty(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'.
在泛型里使用類類型
在TypeScript使用泛型創(chuàng)建工廠函數(shù)時范舀,需要引用構(gòu)造函數(shù)的類類型合是。如:
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!
createInstance(Bee).keeper.nametag; // error: Property 'nametag' does not exist on type 'BeeKeeper'.