TypeScript使用函數(shù)重載確定返回類型的實現(xiàn)方法
自定義一個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); // 初始化返回結果 let values: QueryParamsResult = {}; // 類型守衛(wèi),判斷 key 是否為字符串 if (typeof key === 'string') { values[key] = queryParams.get(key) || ''; } else if (typeof key === 'object' && key !== null) { // 遍歷對象中的每個鍵,并獲取對應的查詢參數(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
,這是一個聯(lián)合類型 string | Record<string, string>
。當你調(diào)用 useGetQueryParams(['templateId'])
時,根據(jù)參數(shù)類型(在這里是一個數(shù)組),返回值應該是一個 Record<string, string>
。
問題是 TypeScript 無法在編譯時確定函數(shù)的返回類型是 string
還是 Record<string, string>
,因為它依賴于函數(shù)的運行時行為。所以,當你嘗試解構返回值并訪問 templateId
屬性時,TypeScript 會拋出錯誤,因為它不確定返回的是不是一個對象。
解決
使用函數(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ù)實現(xiàn) function useGetQueryParams(keys: QueryParamsKeys): string | null | QueryParamsResult { const location = useLocation(); const queryParams = new URLSearchParams(location.search); // 處理單個鍵的情況 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;
雖然我們有多個重載簽名,但只有一個函數(shù)實現(xiàn)。在這個實現(xiàn)內(nèi)部,我們處理所有可能的調(diào)用情況。當函數(shù)被調(diào)用時,TypeScript 編譯器會根據(jù)提供的參數(shù)類型和重載簽名來推斷出哪個重載簽名被使用,并據(jù)此檢查返回類型的一致性。
因此,與普通的 JavaScript 不同,TypeScript 的函數(shù)重載不是真的在運行時提供多個不同的函數(shù)實現(xiàn),而是在編譯時對函數(shù)調(diào)用的類型進行檢查和推斷。實際的 JavaScript 代碼中,仍然只有一個函數(shù)體
注意
在 TypeScript 中,你不能使用箭頭函數(shù)來進行函數(shù)重載。函數(shù)重載是 TypeScript 的一項特性,它允許你為同一個函數(shù)提供多個函數(shù)類型定義。但是,這項特性僅限于傳統(tǒng)的函數(shù)聲明,不適用于箭頭函數(shù),因為箭頭函數(shù)不能被命名。
// 函數(shù)聲明,可以進行重載 function greet(name: string): string; function greet(age: number): string; function greet(single: boolean): string; function greet(value: string | number | boolean): string { // 實際的實現(xiàn)邏輯 return `Hello, ${value}`; }
這是因為在 JavaScript 運行時,不存在函數(shù)重載的概念;它是 TypeScript 在類型系統(tǒng)層面提供的,用于在編譯時檢查和推斷函數(shù)調(diào)用的類型。函數(shù)重載需要一系列具有相同名稱的函數(shù)聲明來實現(xiàn),而箭頭函數(shù)是匿名的,因此不能使用重載。
如果你希望在使用箭頭函數(shù)的同時模擬函數(shù)重載的行為,你可以定義一個具有多個簽名的類型,并將該類型賦給一個變量,然后將箭頭函數(shù)賦給這個變量:
// 定義函數(shù)類型 type GreetFunction = { (name: string): string; (age: number): string; (single: boolean): string; }; // 定義變量并賦予箭頭函數(shù),但實際上這不是函數(shù)重載 const greet: GreetFunction = (value: string | number | boolean): string => { // 實際的實現(xiàn)邏輯 return `Hello, ${value}`; };
上述方法并不是真正的函數(shù)重載,只是模擬函數(shù)重載的行為。盡管這不是真正的重載,但它仍然可以根據(jù)調(diào)用時傳入的參數(shù)類型來返回不同的結果。
為什么箭頭函數(shù)不支持重載:
- 匿名性質:箭頭函數(shù)通常是匿名的,它們沒有函數(shù)名。在 TypeScript 中定義函數(shù)重載時,需要多個具有相同名稱的聲明來表達不同的調(diào)用簽名。
- 聲明方式:在 TypeScript 中,函數(shù)重載是通過列出多個具有相同名稱的函數(shù)聲明來實現(xiàn)的。這是通過在類型層面上對同一個函數(shù)名提供多個類型簽名來完成的。箭頭函數(shù)作為表達式,不具備這種聲明多個類型簽名的能力。
為什么在 TypeScript 中使用函數(shù)聲明進行重載:
- 語法支持:TypeScript 的函數(shù)重載語法是專門為傳統(tǒng)的函數(shù)聲明設計的。
- 編譯器推斷:TypeScript 編譯器可以根據(jù)重載簽名推斷出函數(shù)調(diào)用的返回類型,這為開發(fā)者提供了類型安全。
到此這篇關于TypeScript使用函數(shù)重載確定返回類型的實現(xiàn)方法的文章就介紹到這了,更多相關TypeScript確定返回類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JS動態(tài)修改iframe內(nèi)嵌網(wǎng)頁地址的方法
這篇文章主要介紹了JS動態(tài)修改iframe內(nèi)嵌網(wǎng)頁地址的方法,涉及javascript動態(tài)修改iframe中src屬性的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04