[英]How do I get typescript to infer the return type of a function based on the return type on a function of its arguments
[英]Is there any way to have TypeScript infer the type of a function's return value based on the call arguments?
我正在設置一個 function 將從我的數據庫中檢索數據。 它將鍵字符串作為參數,並根據鍵返回不同的數據類型。
我的目標是讓 TypeScript 根據作為參數傳遞的鍵推斷將返回的類型。
這是我嘗試過的:
interface Fruits { names: string[] }
interface Employees { ages: number[] }
function getData(key: "fruits" | "employees") {
if (key === "fruits") {
// fetch data for /fruits and return it, specifying its type
return { names: ["apple", "orange", "kiwi"] } as Fruits;
}
// fetch data for /employees and return it, specifying its type
return { ages: [30, 50, 19 ] } as Employees;
}
const fruits = getData("fruits");
// ...should infer that the returned value will be of type 'Fruits'
const fruitNames = fruits.names;
// ...fails to infer type. Thinks fruits is of type (Fruits | Employees)
最后一行給出警告,因為 TypeScript 無法推斷在調用 getData 時使用鍵“fruits”將始終返回 Fruits 類型的值(反過來,它具有屬性“names”)。
當然,我也可以通過像這樣對 getData 的調用進行類型轉換來消除錯誤 go :
const fruits = getData("fruits") as Fruits;
但是,在我看來,這違背了首先使用 TypeScript 的目的,因為我的代碼再次變得非常容易出錯。 例如,如果我進行了錯誤的類型轉換,技術上不正確的代碼不會給出任何警告:
const fruits = getData("fruits") as Employees;
const nonexistent = fruits.ages;
// TS won't complain about any accesses to the non-existent property 'ages'
// because I made the wrong typecasting
我的目標是,使用 getData function 的人提前知道,多虧了 TypeScript 的 IntelliSense,一旦他們提供了用於查詢數據的“密鑰”字符串,他們就會立即返回數據類型。 調用 function 時,不必手動對函數的返回值類型進行類型轉換。
在 getData 內部,任何類型轉換、使用 generics 或任何其他類型都可以。 但是,除此之外,給 function 一個有效的鍵參數應該足以讓 TypeScript 推斷出正確的返回類型。
有什么辦法可以做到這一點?
另一種方法是為每個具有適當類型的返回值的鍵聲明function 重載。 您的實現將鍵入key
及其所有可能的值,並具有一個返回類型,該類型是所有可能返回的聯合。 那看起來像:
interface Fruits { names: string[] }
interface Employees { ages: number[] }
function getData(key: "fruits"): Fruits;
function getData(key: "employees"): Employees;
function getData(key: "fruits" | "employees"): Fruits | Employees {
if (key === "fruits") {
// fetch data for /fruits and return it
return { names: ["apple", "orange", "kiwi"] };
}
// fetch data for /employees and return it
return { ages: [30, 50, 19 ] };
}
其實有好幾種方法,這里有一種方法
interface Fruits {
names: string[];
}
interface Employees {
ages: number[];
}
interface DataMap {
fruits: Fruits;
employees: Employees;
}
function getData<T extends keyof DataMap>(key: T): DataMap[T] {
if (key === "fruits") {
// fetch data for /fruits and return it, specifying its type
return { names: ["apple", "orange", "kiwi"] } as DataMap[T];
}
// fetch data for /employees and return it, specifying its type
return { ages: [30, 50, 19] } as DataMap[T];
}
const fruits = getData("fruits"); // knows it's a Fruits
const fruitNames = fruits.names; // works
我們制作了一個輔助類型,用於將 map 字符串轉換為類型,並使用此泛型來捕獲 T 以便我們可以在返回類型中使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.