TypeScript中泛型的使用詳細(xì)講解
一、泛型程序設(shè)計(jì)是一種編程風(fēng)格或編程范式
二、案例:傳入的參數(shù)類(lèi)型與返回的類(lèi)型一樣
function identify<T>(arg: T): T {// 當(dāng)前的T沒(méi)有任何約束 它可以是任何類(lèi)型
return arg;
}
const foo = identify('foo'); // foo的類(lèi)型是'foo'
const bar = identify('true'); // bar的類(lèi)型是true三、形式類(lèi)型參數(shù)
1、形式類(lèi)型參數(shù)T的默認(rèn)類(lèi)型為boolean類(lèi)型
<T = boolean>
2、必選類(lèi)型參數(shù)、可選類(lèi)型參數(shù)
(1)、必選類(lèi)型參數(shù):形式類(lèi)型參數(shù)沒(méi)有給默認(rèn)類(lèi)型 , 例如: <T>
(2)、可選類(lèi)型參數(shù):形式類(lèi)型參數(shù)給默認(rèn)類(lèi)型 , 例如: <T = boolean>
(3)、形式類(lèi)型參數(shù)列表中,必選類(lèi)型參數(shù)不允許出現(xiàn)在可選類(lèi)型參數(shù)之后
<T = boolean, U> // 錯(cuò)誤
<T, U = boolean> // 正確
四、泛型約束
在形式類(lèi)型參數(shù)上允許定義一個(gè)約束條件,它能夠限定類(lèi)型參數(shù)的實(shí)際類(lèi)型的最大范圍。我們將類(lèi)型參數(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è)必須有并且類(lèi)型必須正確 否則錯(cuò)誤可以同時(shí)定義泛型約束和默認(rèn)類(lèi)型
<T extends number = 0 | 1>
泛型約束 ==> 類(lèi)型參數(shù)
<T, U extends T> <T extends U, U>
形式類(lèi)型參數(shù)不允許直接或間接地將其自身作為約束類(lèi)型
<T extends T> // 錯(cuò)誤 <T extends U, U extends T> // 錯(cuò)誤
類(lèi)型參數(shù)T沒(méi)有聲明泛型約束,那么類(lèi)型參數(shù)T的基約束為空對(duì)象類(lèi)型字面量“{}”。除了undefined類(lèi)型和null類(lèi)型外,其他任何類(lèi)型都可以賦值給空對(duì)象類(lèi)型字面量
<T> // 類(lèi)型參數(shù)T的基數(shù)約為“{}”類(lèi)型五、泛型函數(shù)
1.簡(jiǎn)介:若一個(gè)函數(shù)的函數(shù)簽名(形參)中帶有類(lèi)型參數(shù),那么它是一個(gè)泛型函數(shù)
2.f1函數(shù)兩個(gè)參數(shù)的類(lèi)型相同,函數(shù)返回值類(lèi)型是數(shù)組,數(shù)組元素類(lèi)型 == 參數(shù)類(lèi)型。
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ù)的類(lèi)型不同,返回值類(lèi)型為對(duì)象類(lèi)型。返回值對(duì)象類(lèi)型中x屬性的類(lèi)型與參數(shù)x類(lèi)型相同,y屬性的類(lèi)型與參數(shù)y類(lèi)型相同
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為任意類(lèi)型的數(shù)組;參數(shù)f是一個(gè)函數(shù),該函數(shù)的參數(shù)類(lèi)型與參數(shù)a的類(lèi)型相同,并返回任意類(lèi)型。f3函數(shù)的返回值類(lèi)型為參數(shù)f返回值類(lèi)型的數(shù)組。
(這個(gè)代碼的粘貼的 我也懵逼)
function f3<T, U>(a: T[], f: (x: T) => U): U[] {
return a.map(f);
}
// f3<number, boolean> 約束T為number類(lèi)型 U為boolean類(lèi)型
const a: boolean[] = f3<number, boolean>([1, 2, 3], n => !! n)六、泛型函數(shù)類(lèi)型推斷
function f0<T>(x: T): T {
return x
}
const a = f0(123) // 推斷出類(lèi)型為 123
const b = f0('123') // 推斷出類(lèi)型為 '123'此例中編譯器推斷出的不是number 和 string類(lèi)型,而是字符串字面量類(lèi)型123和“123”。因?yàn)門(mén)S原則,始終將字面量視為字面量類(lèi)型,只在必要的時(shí)候才會(huì)將字面量類(lèi)型放寬為某種基礎(chǔ)類(lèi)型,例如string類(lèi)型。此例中,字符串字面量類(lèi)型“123”是比string類(lèi)型更加精確的類(lèi)型。
類(lèi)型參數(shù)只在函數(shù)簽名中出現(xiàn)一次,則說(shuō)明它與其他值沒(méi)有關(guān)聯(lián),則不需要使用類(lèi)型參數(shù),直接聲明實(shí)際類(lèi)型即可。
幾乎任何函數(shù)都可以聲明為泛型函數(shù)。若泛型函數(shù)的類(lèi)型參數(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ò)上面初步的了解,后述在編寫(xiě) typescript 的時(shí)候,定義函數(shù),接口或者類(lèi)的時(shí)候,不預(yù)先定義好具體的類(lèi)型,而在使用的時(shí)候在指定類(lèi)型的一種特性的時(shí)候,這種情況下就可以使用泛型
靈活的使用泛型定義類(lèi)型,是掌握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',
},
];
泛型類(lèi)
/*--------------泛型類(lèi)---------------*/
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)泛型約束,寫(xiě)法如:
<泛型變量 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)類(lèi)型推導(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)文章希望大家以后多多支持腳本之家!
- TypeScript泛型工作原理詳解
- TypeScript?泛型接口具體使用實(shí)戰(zhàn)
- TypeScript之Generics泛型類(lèi)型學(xué)習(xí)
- TypeScript接口與泛型全面精講
- TypeScript泛型使用詳細(xì)介紹
- TypeScript泛型的使用詳細(xì)介紹
- TypeScript?泛型推斷實(shí)現(xiàn)示例詳解
- TypeScript?泛型重載函數(shù)的使用方式
- 在?TypeScript?中使用泛型的方法
- TypeScript泛型約束條件示例詳解
- typeScript?泛型使用和泛型接口結(jié)合
- TypeScript 泛型四大應(yīng)用場(chǎng)景與高級(jí)用法
相關(guān)文章
SOSO地圖JS畫(huà)出標(biāo)注和中心點(diǎn)以html形式運(yùn)行
SOSO地圖想必大家都知道吧,本文將為大家詳細(xì)介紹下使用JS畫(huà)出標(biāo)注和中心點(diǎn),直接貼出代碼,感興趣的朋友可以參考下2013-08-08
Webstorm開(kāi)發(fā)uni-app項(xiàng)目詳細(xì)圖文教程
這篇文章主要介紹了使用WebStorm和UniappTool創(chuàng)建和運(yùn)行uni-app項(xiàng)目的相關(guān)資料,包括配置微信開(kāi)發(fā)者工具和運(yùn)行項(xiàng)目,同時(shí)提到了創(chuàng)建新頁(yè)面和使用uniapptool存在的弊端,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-11-11
mockjs,json-server一起搭建前端通用的數(shù)據(jù)模擬框架教程
下面小編就為大家分享一篇mockjs,json-server一起搭建前端通用的數(shù)據(jù)模擬框架教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
javascript實(shí)現(xiàn)自動(dòng)填寫(xiě)表單實(shí)例簡(jiǎn)析
這篇文章主要介紹了javascript實(shí)現(xiàn)自動(dòng)填寫(xiě)表單的方法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了JavaScript結(jié)合瀏覽器設(shè)置實(shí)現(xiàn)自動(dòng)保存表單的相關(guān)技巧,需要的朋友可以參考下2015-12-12
javascript實(shí)現(xiàn)二叉樹(shù)的代碼
本篇文章主要介紹了javascript實(shí)現(xiàn)二叉樹(shù)的代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
JavaScript經(jīng)典案例之簡(jiǎn)易計(jì)算器
這篇文章主要為大家詳細(xì)介紹了JavaScript經(jīng)典案例之簡(jiǎn)易計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
基于ssm框架實(shí)現(xiàn)layui分頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了基于ssm框架實(shí)現(xiàn)layui分頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
JavaScript QueryString解析類(lèi)代碼
以前寫(xiě)的一個(gè)解析QueryString的JS類(lèi),可以獲取或設(shè)置QueryString中的值,記下了方便找 :)2010-01-01

