TypeScript中泛型的使用詳細(xì)講解
一、泛型程序設(shè)計(jì)是一種編程風(fēng)格或編程范式
二、案例:傳入的參數(shù)類型與返回的類型一樣
function identify<T>(arg: T): T {// 當(dāng)前的T沒(méi)有任何約束 它可以是任何類型 return arg; } const foo = identify('foo'); // foo的類型是'foo' const bar = identify('true'); // bar的類型是true
三、形式類型參數(shù)
1、形式類型參數(shù)T的默認(rèn)類型為boolean類型
<T = boolean>
2、必選類型參數(shù)、可選類型參數(shù)
(1)、必選類型參數(shù):形式類型參數(shù)沒(méi)有給默認(rèn)類型 , 例如: <T>
(2)、可選類型參數(shù):形式類型參數(shù)給默認(rèn)類型 , 例如: <T = boolean>
(3)、形式類型參數(shù)列表中,必選類型參數(shù)不允許出現(xiàn)在可選類型參數(shù)之后
<T = boolean, U> // 錯(cuò)誤
<T, U = boolean> // 正確
四、泛型約束
在形式類型參數(shù)上允許定義一個(gè)約束條件,它能夠限定類型參數(shù)的實(shí)際類型的最大范圍。我們將類型參數(shù)的約束條件稱為泛型約束
interface point { x: number, y: string } function getPoint<T extends point>(args: T): T { return args } console.log(getPoint({x: 123, y: 456})); // 錯(cuò)誤 console.log(getPoint({x: 123, y: '456'})); // 正確 console.log(getPoint({x: 123, y: '456', z: 678})); // 正確 //參數(shù)的前倆個(gè)必須有并且類型必須正確 否則錯(cuò)誤
可以同時(shí)定義泛型約束和默認(rèn)類型
<T extends number = 0 | 1>
泛型約束 ==> 類型參數(shù)
<T, U extends T> <T extends U, U>
形式類型參數(shù)不允許直接或間接地將其自身作為約束類型
<T extends T> // 錯(cuò)誤 <T extends U, U extends T> // 錯(cuò)誤
類型參數(shù)T沒(méi)有聲明泛型約束,那么類型參數(shù)T的基約束為空對(duì)象類型字面量“{}”。除了undefined類型和null類型外,其他任何類型都可以賦值給空對(duì)象類型字面量
<T> // 類型參數(shù)T的基數(shù)約為“{}”類型
五、泛型函數(shù)
1.簡(jiǎn)介:若一個(gè)函數(shù)的函數(shù)簽名(形參)中帶有類型參數(shù),那么它是一個(gè)泛型函數(shù)
2.f1函數(shù)兩個(gè)參數(shù)的類型相同,函數(shù)返回值類型是數(shù)組,數(shù)組元素類型 == 參數(shù)類型。
function f1<T>(x: T, y: T): T[] { return [x, y] } const a = f1(123, 456) const b = f1('123', '456')
3.f2函數(shù)兩個(gè)參數(shù)的類型不同,返回值類型為對(duì)象類型。返回值對(duì)象類型中x屬性的類型與參數(shù)x類型相同,y屬性的類型與參數(shù)y類型相同
function f2<T, U>(x: T, y: U): { x: T, y: U} { return { x, y } } const a = f2('123', 456) const b = f2(123, '456')
4.f3函數(shù)接受兩個(gè)參數(shù),參數(shù)a為任意類型的數(shù)組;參數(shù)f是一個(gè)函數(shù),該函數(shù)的參數(shù)類型與參數(shù)a的類型相同,并返回任意類型。f3函數(shù)的返回值類型為參數(shù)f返回值類型的數(shù)組。
(這個(gè)代碼的粘貼的 我也懵逼)
function f3<T, U>(a: T[], f: (x: T) => U): U[] { return a.map(f); } // f3<number, boolean> 約束T為number類型 U為boolean類型 const a: boolean[] = f3<number, boolean>([1, 2, 3], n => !! n)
六、泛型函數(shù)類型推斷
function f0<T>(x: T): T { return x } const a = f0(123) // 推斷出類型為 123 const b = f0('123') // 推斷出類型為 '123'
此例中編譯器推斷出的不是number 和 string類型,而是字符串字面量類型123和“123”。因?yàn)門S原則,始終將字面量視為字面量類型,只在必要的時(shí)候才會(huì)將字面量類型放寬為某種基礎(chǔ)類型,例如string類型。此例中,字符串字面量類型“123”是比string類型更加精確的類型。
類型參數(shù)只在函數(shù)簽名中出現(xiàn)一次,則說(shuō)明它與其他值沒(méi)有關(guān)聯(lián),則不需要使用類型參數(shù),直接聲明實(shí)際類型即可。
幾乎任何函數(shù)都可以聲明為泛型函數(shù)。若泛型函數(shù)的類型參數(shù)不表示參數(shù)之間或參數(shù)與返回值之間的某種關(guān)系,那么使用泛型函數(shù)可能是一種反模式。
// 沒(méi)必要使用泛型 function f<T>(x: T): void { console.log(x) } // 直接限定就好了 function f(x: number): void { console.log(x) }
補(bǔ)充:應(yīng)用場(chǎng)景
通過(guò)上面初步的了解,后述在編寫 typescript 的時(shí)候,定義函數(shù),接口或者類的時(shí)候,不預(yù)先定義好具體的類型,而在使用的時(shí)候在指定類型的一種特性的時(shí)候,這種情況下就可以使用泛型
靈活的使用泛型定義類型,是掌握typescript 必經(jīng)之路
<泛型變量名稱>(參數(shù)1: 泛型變量, 參數(shù)2: 泛型變量, ...參數(shù)n: 泛型變量) => 泛型變量
/*------------基礎(chǔ)使用方法------------*/ function join<T, P>(first: T, second: P): T { return first; } //const twoParms = join<number, string>(1, '我是string'); const twoParms = join(1, '我是string'); /*---------泛型集合--------------*/ function map<T>(params: Array<T>) { return params; } //const sanleType = map<string>(['123']); const sanleType = map(['123']); /* -----------泛型箭頭函數(shù)-------------*/ const identity = <T,>(arg: T): T => { return arg; }; const identity2: <T>(arg: T) => T = (arg) => { return arg; };
泛型接口
/* -------------泛型接口-------------*/ interface ColumnProps<T> { key: number | string; title: string; dataIndex: keyof T; // 約束 dataIndex 值需為引用泛型 T 中的屬性 } interface ITableItem { key: number | string; name: string; address: string; age: number; } const columns: Array<ColumnProps<ITableItem>> = [ { title: '姓名', dataIndex: 'name', key: 'name', }, ];
泛型類
/*--------------泛型類---------------*/ class Person<T> { love: T; say: (arg: T) => T; } let myFn: IGeneric<number> = fn; myFn(13); //13 let me = new Person<string>(); me.love = 'TS'; // me.love = 520; // ERROR me.say = function(love: string){ return `my love is ${love}`; }
泛型約束
泛型可以通過(guò) extends 一個(gè)接口來(lái)實(shí)現(xiàn)泛型約束,寫法如:
<泛型變量 extends 接口>
<T, K extends keyof T> //K為傳入的T上已知的屬性, interface IArray { length: number } function logIndex<T extends IArray>(arg: T): void { for (let i = 0; i < arg.length; ++i) { console.log(i) } } let arr = [1, 2, 3] // logIndex<number>(arr) // 報(bào)錯(cuò) logIndex<number[]>(arr) // 允許 logIndex(arr) // 自動(dòng)類型推導(dǎo),允許
泛型應(yīng)用場(chǎng)景之一
/*-------------應(yīng)用場(chǎng)景start---------------------------*/ interface ColumnProps<T> { key: number | string; title: string; dataIndex: keyof T; // 約束 dataIndex 值需為引用泛型 T 中的屬性 } interface ITableItem { key: number | string; name: string; address: string; age: number; } interface TableProps { dataSource: ITableItem[]; columns: Array<ColumnProps<ITableItem>>; } const MyTable = (props: TableProps) => { const { dataSource, columns } = props; return <Table dataSource={dataSource} columns={columns} />; }; const ApplcationMod = () => { const dataSource = [ { key: '1', name: '金城武', age: 32, address: '西湖區(qū)湖底公園1號(hào)', }, { key: '2', name: '吳彥祖', age: 42, address: '西湖區(qū)湖底公園1號(hào)', }, ]; const columns: Array<ColumnProps<ITableItem>> = [ { title: '姓名', dataIndex: 'name', key: 'name', }, { title: '年齡', dataIndex: 'age', key: 'age', }, { title: '住址', dataIndex: 'address', key: 'address', }, ]; return ( <div> <h3>泛型應(yīng)用場(chǎng)景</h3> <MyTable dataSource={dataSource} columns={columns} /> </div> ); };
總結(jié)
到此這篇關(guān)于TypeScript中泛型使用的文章就介紹到這了,更多相關(guān)TypeScript泛型的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
GreyBox技術(shù)總結(jié)(轉(zhuǎn))
GreyBox是一個(gè)遮罩層的組件也稱模式窗口或模態(tài)窗口(所謂模態(tài)窗口,就是指除非采取有效的關(guān)閉手段,用戶的鼠標(biāo)焦點(diǎn)或者輸入光標(biāo)將一直停留在其上的窗口),它運(yùn)行以后可以產(chǎn)生不錯(cuò)的界面。2010-11-11JavaScript前端開(kāi)發(fā)之實(shí)現(xiàn)二進(jìn)制讀寫操作
這篇文章主要介紹了JavaScript前端開(kāi)發(fā)之實(shí)現(xiàn)二進(jìn)制讀寫操作的相關(guān)資料,需要的朋友可以參考下2015-11-11javascript生成不重復(fù)的隨機(jī)數(shù)
這篇文章主要介紹了javascript在指定范圍內(nèi)生成不重復(fù)的隨機(jī)數(shù)的方法和相關(guān)實(shí)例,有需要的小伙伴可以參考下。2015-07-07javascript和jquery分別實(shí)現(xiàn)的九九乘法表代碼
javascript 九九乘法表 附j(luò)query 實(shí)現(xiàn)的九九乘法表代碼2010-03-03JS頁(yè)面刷新與重新加載功能實(shí)現(xiàn)(關(guān)閉當(dāng)前窗口)
在計(jì)算機(jī)網(wǎng)頁(yè)中如果我們想獲取當(dāng)前頁(yè)面最新的內(nèi)容,可以刷新當(dāng)前頁(yè)面重新獲取數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于JS頁(yè)面刷新與重新加載功能實(shí)現(xiàn)(關(guān)閉當(dāng)前窗口)的相關(guān)資料,需要的朋友可以參考下2023-10-10JavaScript實(shí)現(xiàn)鼠標(biāo)移入隨機(jī)變換顏色
這篇文章主要給大家介紹了關(guān)于JavaScript實(shí)現(xiàn)鼠標(biāo)移入隨機(jī)變換顏色的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11js實(shí)現(xiàn)二級(jí)菜單點(diǎn)擊顯示當(dāng)前內(nèi)容效果
這篇文章主要介紹了js實(shí)現(xiàn)二級(jí)菜單點(diǎn)擊顯示當(dāng)前內(nèi)容效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04