TypeScript使用函數(shù)重載確定返回類型的實(shí)現(xiàn)方法
自定義一個(gè)hooks
import { useLocation } from 'react-router-dom'; // 定義 QueryParamsKey 類型為 string 或 Record<string, string> type QueryParamsKey = string | Record<string, string>; // 定義返回類型 type QueryParamsResult = Record<string, string>; const useGetQueryParams = (key: QueryParamsKey): QueryParamsResult => { const location = useLocation(); const queryParams = new URLSearchParams(location.search); // 初始化返回結(jié)果 let values: QueryParamsResult = {}; // 類型守衛(wèi),判斷 key 是否為字符串 if (typeof key === 'string') { values[key] = queryParams.get(key) || ''; } else if (typeof key === 'object' && key !== null) { // 遍歷對(duì)象中的每個(gè)鍵,并獲取對(duì)應(yīng)的查詢參數(shù) Object.keys(key).forEach((k) => { // 使用 key 中的值作為查詢參數(shù)的鍵 values[k] = queryParams.get(key[k]) || ''; }); } return values; }; export default useGetQueryParams;
問題:
使用 const {templateId} = useGetQueryParams(['templateId'])
提示類型“QueryParamsResultValues”上不存在屬性“templateId”。
解釋:
useGetQueryParams
函數(shù)的返回類型被定義為 QueryParamsResultValues
,這是一個(gè)聯(lián)合類型 string | Record<string, string>
。當(dāng)你調(diào)用 useGetQueryParams(['templateId'])
時(shí),根據(jù)參數(shù)類型(在這里是一個(gè)數(shù)組),返回值應(yīng)該是一個(gè) Record<string, string>
。
問題是 TypeScript 無法在編譯時(shí)確定函數(shù)的返回類型是 string
還是 Record<string, string>
,因?yàn)樗蕾囉诤瘮?shù)的運(yùn)行時(shí)行為。所以,當(dāng)你嘗試解構(gòu)返回值并訪問 templateId
屬性時(shí),TypeScript 會(huì)拋出錯(cuò)誤,因?yàn)樗淮_定返回的是不是一個(gè)對(duì)象。
解決
使用函數(shù)聲明式函數(shù)重載來讓 TypeScript 根據(jù)不同的參數(shù)類型來推斷不同的返回類型
import { useLocation } from 'react-router'; type QueryParamsKeys = string | string[]; type QueryParamsResult = Record<string, string | null>; // 函數(shù)重載聲明 function useGetQueryParams(key: string): string | null; function useGetQueryParams(keys: string[]): QueryParamsResult; // 函數(shù)實(shí)現(xiàn) function useGetQueryParams(keys: QueryParamsKeys): string | null | QueryParamsResult { const location = useLocation(); const queryParams = new URLSearchParams(location.search); // 處理單個(gè)鍵的情況 if (typeof keys === 'string') { return queryParams.get(keys); } // 處理鍵數(shù)組的情況 else if (Array.isArray(keys)) { const values: QueryParamsResult = {}; keys.forEach((k) => { values[k] = queryParams.get(k); }); return values; } throw new Error('Invalid keys argument'); } export default useGetQueryParams;
雖然我們有多個(gè)重載簽名,但只有一個(gè)函數(shù)實(shí)現(xiàn)。在這個(gè)實(shí)現(xiàn)內(nèi)部,我們處理所有可能的調(diào)用情況。當(dāng)函數(shù)被調(diào)用時(shí),TypeScript 編譯器會(huì)根據(jù)提供的參數(shù)類型和重載簽名來推斷出哪個(gè)重載簽名被使用,并據(jù)此檢查返回類型的一致性。
因此,與普通的 JavaScript 不同,TypeScript 的函數(shù)重載不是真的在運(yùn)行時(shí)提供多個(gè)不同的函數(shù)實(shí)現(xiàn),而是在編譯時(shí)對(duì)函數(shù)調(diào)用的類型進(jìn)行檢查和推斷。實(shí)際的 JavaScript 代碼中,仍然只有一個(gè)函數(shù)體
注意
在 TypeScript 中,你不能使用箭頭函數(shù)來進(jìn)行函數(shù)重載。函數(shù)重載是 TypeScript 的一項(xiàng)特性,它允許你為同一個(gè)函數(shù)提供多個(gè)函數(shù)類型定義。但是,這項(xiàng)特性僅限于傳統(tǒng)的函數(shù)聲明,不適用于箭頭函數(shù),因?yàn)榧^函數(shù)不能被命名。
// 函數(shù)聲明,可以進(jìn)行重載 function greet(name: string): string; function greet(age: number): string; function greet(single: boolean): string; function greet(value: string | number | boolean): string { // 實(shí)際的實(shí)現(xiàn)邏輯 return `Hello, ${value}`; }
這是因?yàn)樵?JavaScript 運(yùn)行時(shí),不存在函數(shù)重載的概念;它是 TypeScript 在類型系統(tǒng)層面提供的,用于在編譯時(shí)檢查和推斷函數(shù)調(diào)用的類型。函數(shù)重載需要一系列具有相同名稱的函數(shù)聲明來實(shí)現(xiàn),而箭頭函數(shù)是匿名的,因此不能使用重載。
如果你希望在使用箭頭函數(shù)的同時(shí)模擬函數(shù)重載的行為,你可以定義一個(gè)具有多個(gè)簽名的類型,并將該類型賦給一個(gè)變量,然后將箭頭函數(shù)賦給這個(gè)變量:
// 定義函數(shù)類型 type GreetFunction = { (name: string): string; (age: number): string; (single: boolean): string; }; // 定義變量并賦予箭頭函數(shù),但實(shí)際上這不是函數(shù)重載 const greet: GreetFunction = (value: string | number | boolean): string => { // 實(shí)際的實(shí)現(xiàn)邏輯 return `Hello, ${value}`; };
上述方法并不是真正的函數(shù)重載,只是模擬函數(shù)重載的行為。盡管這不是真正的重載,但它仍然可以根據(jù)調(diào)用時(shí)傳入的參數(shù)類型來返回不同的結(jié)果。
為什么箭頭函數(shù)不支持重載:
- 匿名性質(zhì):箭頭函數(shù)通常是匿名的,它們沒有函數(shù)名。在 TypeScript 中定義函數(shù)重載時(shí),需要多個(gè)具有相同名稱的聲明來表達(dá)不同的調(diào)用簽名。
- 聲明方式:在 TypeScript 中,函數(shù)重載是通過列出多個(gè)具有相同名稱的函數(shù)聲明來實(shí)現(xiàn)的。這是通過在類型層面上對(duì)同一個(gè)函數(shù)名提供多個(gè)類型簽名來完成的。箭頭函數(shù)作為表達(dá)式,不具備這種聲明多個(gè)類型簽名的能力。
為什么在 TypeScript 中使用函數(shù)聲明進(jìn)行重載:
- 語法支持:TypeScript 的函數(shù)重載語法是專門為傳統(tǒng)的函數(shù)聲明設(shè)計(jì)的。
- 編譯器推斷:TypeScript 編譯器可以根據(jù)重載簽名推斷出函數(shù)調(diào)用的返回類型,這為開發(fā)者提供了類型安全。
到此這篇關(guān)于TypeScript使用函數(shù)重載確定返回類型的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)TypeScript確定返回類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用ES6的class模仿Vue寫一個(gè)雙向綁定的示例代碼
本篇文章主要介紹了用ES6的class模仿Vue寫一個(gè)雙向綁定的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04js實(shí)現(xiàn)圖片和鏈接文字同步切換特效的方法
這篇文章主要介紹了js實(shí)現(xiàn)圖片和鏈接文字同步切換特效的方法,涉及javascript操作文字及圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02JavaScript動(dòng)態(tài)插入CSS的方法
這篇文章主要介紹了JavaScript動(dòng)態(tài)插入CSS的方法,兩個(gè)步驟就可以實(shí)現(xiàn)JavaScript動(dòng)態(tài)插入CSS2015-12-12JS作用域閉包、預(yù)解釋和this關(guān)鍵字綜合實(shí)例解析
這篇文章主要介紹了JS作用域閉包、預(yù)解釋和this關(guān)鍵字,結(jié)合實(shí)例形式分析了javascript作用域閉包、預(yù)解釋和this關(guān)鍵字在具體使用過程中的操作技巧與注意事項(xiàng),需要的朋友可以參考下2016-12-12js操作時(shí)間(年-月-日 時(shí)-分-秒 星期幾)
js操作時(shí)間(年-月-日 時(shí)-分-秒 星期幾),需要的朋友可以參考下。2010-06-06JS動(dòng)態(tài)修改iframe內(nèi)嵌網(wǎng)頁(yè)地址的方法
這篇文章主要介紹了JS動(dòng)態(tài)修改iframe內(nèi)嵌網(wǎng)頁(yè)地址的方法,涉及javascript動(dòng)態(tài)修改iframe中src屬性的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04