0.泛型基本用法:
- 在軟件工程中,我們不僅要創建一致的定義良好的API,同時也要考慮可重用性。組件不僅能支持當前數據類型,同時也能支持未來的數據類型,這在創建大型系統時為你提供了十分靈活的功能
- 簡而言之:泛型就是解決 類、接口、方法的復用性,以及對不特定數據類型的支持
在ts中,比如一個函數要支持傳入類型與返回類型支持多種數據類型,可以使用any,any就是完全放棄了數據類型檢查
ts中的泛型:<T>
可以支持不特定的數據類型
示例1:要求,傳入的參數和返回的參數一致
function getData<T>(value: T): T { return value; } // 類型檢查和傳入參數必須一致 console.log(getData<number>(123)); console.log(getData<string>('abc'));
示例2:返回數組的兩個值
function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]] } const result = swap([123, 'abc']) result[1].toFixed(2)
可以把它看成一個占位符,使用的時候才動態的填入類型值
1.約束泛型
有時對某個類型的泛型要調用該泛型內的方法,例如:
function echoWithArr<T>(arg: T): T { console.log(arg.length) return arg }
如果此時傳入的是number類型的參數,就沒有length屬性,且會提示:
這里可以使用泛型約束了
function echoWithArr<T>(arg: T[]): T[] { console.log(arg.length) return arg } const arr = echoWithArr([1, 2, 3])
上面代碼中約束了傳入的參數需要是任意類型的數組,但是,Object,String類型都是有length屬性的,這時候就不滿足這種場景了。這時候需要對泛型進行約束,允許這個函數傳入包含length屬性的變量(約束泛型):
interface IWithLength { length: number } function echoWithLength<T extends IWithLength>(arg: T): T { console.log(arg.length) return arg } const len01 = echoWithLength('abc') // 3 const len02 = echoWithLength({ length: 12 }) // 12 const len03 = echoWithLength([1, 2, 3]) // 3
上面代碼中,定義了一個接口IWithLength,在函數echoWithLength的泛型中使用extends關鍵字繼承自這個接口,表示這個泛型必須要有length這個屬性。
2.泛型類:
如有個方法,需要同時支持返回字符串和數字兩種類型,需要通過泛型類來實現
class MinClass<T>{ public list: T[] = []; add(value: T): void { this.list.push(value); } min(): T { let minNum = this.list[0]; for (let e of this.list) { if (minNum > e) { minNum = e } } return minNum; } } // 制定類的代表類型是number let m = new MinClass<number>(); //實例化類,並且制定了類的代表類型是number m.add(5); m.add(9); m.add(12); m.add(4); console.log(m.min()); // 制定類的代表類型是number let m1 = new MinClass<string>(); m1.add('d'); m1.add('f'); m1.add('z'); m1.add('q'); console.log(m1.min());
3.泛型接口
先看看函數類型接口:
interface ConfigFn{ (value1:string,value2:string):string; } let setData:ConfigFn=function(v1:string,v2:string):string{ return v1+v2; } setData('name','張三');
未完待續。。