《四》大话 TypeScript 泛型
——點擊上方藍色字體,關注我哦~——
前言: 本文章為 TypeScript 系列文章.?
旨在利用碎片時間快速入門 Typescript. 或重新溫故 Typescript 查漏補缺.
在官方 api 的基礎上, 加上一些日常使用的感想.?
如果感興趣的話~ 歡迎關注, 后續持續推出文章.?
文章列表:?
《一》大話 TypeScript?基本類型
《二》大話 Typescript 枚舉
《三》大話?Typescript 接口
《四》大話 Typescript 泛型
《五》大話 Typescript 函數
《六》大話 Typescript 類
《七》大話 Typescript 類型推斷
……
目錄結構
為何要用泛型
泛型約束
泛型語法
實際應用
高級類型: 索引類型
react 實際場景
?
為何要用泛型
javascript 作為一門動態語言, 在實際運行的時候,等變量被賦值才知道該變量的類型. 動態語言給實際的編碼帶來了很大的靈活性.
function getVal(val) {
? ?retrurn val;
}
getVal(1) // 返回數字類型
getVal('1') // 返回字符串類型
getVal(['2']) // 返回數組類型
但是同樣的, 在代碼運行期間有可能會發生與類型相關的錯誤, 降低了代碼的可維護性. 那下面我們用 typescript 來定義變量. 為了支持3種調用方式, 我們需要聲明三種類型定義.?
有2種方法可以解決上面這個問題.?
1. 函數重載
function getVal(val: number): number
function getVal(val: string):string
function getVal(val: any):any {
? ?return val;
}
2.?聯合類型function getVal(val: string | number | any[]):string | number | any[] {
? ?????return val;
????}
作為一個程序員, 上面2種方法讓我們感受重復繁瑣. 這是無法容忍的. 那怎么樣可以讓該函數又可以在運行的時候被賦值才確定該變量的類型, 又有一定的類型約束減少相關的錯誤? 答案就是: 泛型
function getVal<T>(val: T): T {
? ?return val;
}
T 即代表捕獲函數傳入的參數類型, 然后在函數內部使用 T 即用該參數類型聲明其他變量.?
但是我們從上面的函數看出, 因為 T 是捕獲參數傳入的參數類型,?
而這個函數可以傳入任意參數, 與我們最開始只支持3個類型的需求不符. 所以下面要引入泛型約束.
泛型約束
type Params= ?string | number | any[];
function getVal<T extends Params>(val: T): T {
? ?return val;
}
getVal(1);
getVal('2');
getVal(['222']);
getVal<number>('3'); // 跟泛型指定的類型不一致, 報錯
getVal({}); // 不是 Param 類型, 報錯
泛型語法
泛型即可以聲明函數, 也可以聲明類. 也可以聲明接口
class Person<T>{} // 一個尖括號跟在類名后面
function Person<T> {} ?// 一個尖括號跟在函數名后面
interface Person<T> {} ?// 一個尖括號跟在接口名后面
有些時候, 一個類或者一個函數里面, 他不止要用到一個動態類型, 他要用到多個. 但是我們上面只能捕獲一個, 那直接聲明多個即可。?
function getName<T,U> (name: T, id: U): [T, U] {
? ?return [name, id]
}
getName('peen', 1);
getName('peen', '222'); // 正常
getName<string, number>('peen', '22'); // 報錯: '22'不是number類型
實際應用
在實際項目中, 每個項目都需要接口請求, 我們會封裝一個通用的接口請求, 在這個函數里面, 處理一些常見的錯誤等等.?
為了讓每個接口調用都有 typescript 約束, 提醒. 這里使用泛型是非常合適了.?
interface IApiSourceParams {
? ?GetList: IGetList
}
interface IGetList {
? ?id: number;
}
export function fetchApi<T extends keyof IApiSourceParams>
(action: T, params: IApiSourceParams[T]) {
? ?return ajax({
? ? ? ?url: action,
? ? ? ?method: 'POST',
? ? ? ?body: params
? ?})
}
fetchApi('GetList', { id: 2 });
fetchApi('GetList', { id: '33' }); // 報錯, id 應該是 number 類型
這樣子, 我們就給一個通用的接口請求函數增加了類型約束. 在 IApiSourceParams 中擴展每一個接口類型即可.?
從上面的例子看到了 T extends keyof IApiSourceParams ,?
實際這種應用場景特別多. ?這要講 索引類型。?
高級類型: 索引類型
索引類型查詢操作符: keyof , 對于任何類型 T, keyof T的結果為 T上已知的公共屬性名的聯合. 看著話有點繞, 直接看例子吧
interface Person {
? ?name: string;
? ?age: number;
}
let personProps: keyof Person; // 'name' | 'age'
索引訪問操作符 : T[K] .??
上面的 keyof 實際就是獲取了對象的鍵值, 看一下上面的實際例子
interface IApiSourceParams {
? ?GetList: IGetList,
? ?PostApi: IPostApi
}
interface IGetList {
? ?id: number;
}
export function fetchApi<T extends keyof IApiSourceParams>
(action: T, params: IApiSourceParams[T]) {
? ?return ajax({
? ? ? ?url: action,
? ? ? ?method: 'POST',
? ? ? ?body: params
? ?})
}
// IApiSourceParams[T] 獲取的便是接口 IApiSourceParams 對應key值的接口
IGetList.
react 實際場景
泛型在各大庫中都非常廣泛的使用, 下面選react中的類和react hook 實地分析
一、react 類?
如果使用過 react , 肯定見過下面這種語法聲明 props 和 state
class Test extends Component<IProps, IState> {}
我們再看看 react class 里面的 typescript 聲明
class Component<P, S> {
? ?static contextType?: Context<any>;
? ?context: any;
? ?constructor(props: Readonly<P>);
? ?constructor(props: P, context?: any);
? ?setState<K extends keyof S>(
? ? ? ?state: ((prevState: Readonly<S>, props: Readonly<P>) =>
????(Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
? ? ? ?callback?: () => void
? ?): void;
? ?forceUpdate(callBack?: () => void): void;
? ?render(): ReactNode;
? ?readonly props: Readonly<P> & Readonly<{ children?: ReactNode }>;
? ?state: Readonly<S>;
? ?refs: {
? ? ? ?[key: string]: ReactInstance
? ?};
}
可以看到react以及提前幫忙做好了一些約束
1. constructor 的 props 屬性都是只讀屬性
2. setState 只能是 K extends keyof , 聲明的 state 里面的類型.
3. ……
二、react HOOK?
我們隨便找一個最常使用的 useState 方法.?
function useState<S>(initialState: S | (() => S)): [S,
Dispatch<SetStateAction<S>>];
function useState<S = undefined>(): [S | undefined,
Dispatch<SetStateAction<S | undefined>>];
所以我們在使用的時候, 可以
const [errorMessage, setError] = useState<string>('');
總結
最后\
本篇文章講了泛型解決的場景以及語法. 并介紹了一些實際的應用場景.?
最后歡迎關注「前端加加」,認真學前端,做個有專業的技術人...
最后
掃描二維碼
關注前端加加
我在這里等你呦~
-?歡迎關注「前端加加」,認真學前端,做個有專業的技術人...
原創不易,如果覺得有點用,希望可以隨手轉發或者”在看“,拜謝各位老鐵。
點擊在看
總結
以上是生活随笔為你收集整理的《四》大话 TypeScript 泛型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宝德自强PT620Z1
- 下一篇: Hulu是什么?中国也有了?