簡體   English   中英

有沒有辦法讓 TypeScript 根據調用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM