簡體   English   中英

如何通過其參數正確鍵入 function 的返回類型

[英]How to Correctly Type Return type of function by its parameter

我正在嘗試實現一個 function 根據其參數返回不同類型的值。

我可以只使用 javascript 來做到這一點,但我希望 Typescript 也能正確推斷此 function 的返回類型。 所以我使用Generic提取返回類型,但是每個return語句都會報TS(2322)錯誤。

有沒有更好的方法來正確使用 TypeScript 鍵入函數的返回值?

下面是我的代碼的簡化版本。

type Context = "Acontext" | "Bcontext";

type A = "a";
type B = "b";

type AorB<T extends Context> = T extends "Acontext"
  ? A
  : T extends "Bcontext"
  ? B
  : never;

const testFunction = <T extends Context>(context: T): AorB<T> => {
  const aObject: A = "a";
  const bObject: B = "b";

  switch (context) {
    case "Acontext":
      return aObject;
    case "Bcontext":
      return bObject;
    default:
      throw new Error(`Invalid Context Type : ${context}`);
  }
};

這是錯誤信息。 在此處輸入圖像描述

這是我的代碼框鏈接。 https://codesandbox.io/s/nostalgic-fast-5ixmsl?file=/src/index.ts:0-477

TypeScript 不支持條件類型代替返回類型。 為了實現它,您應該使用 function 重載。

type Context = "Acontext" | "Bcontext";

type A = "a";
type B = "b";

type AorB<T extends Context> = T extends "Acontext"
    ? A
    : T extends "Bcontext"
    ? B
    : never;

function testFunction<T extends Context>(context: T): AorB<T>
function testFunction<T extends Context>(context: T) {
    const aObject: A = "a";
    const bObject: B = "b";

    switch (context) {
        case "Acontext":
            return aObject;
        case "Bcontext":
            return bObject;
        default:
            throw new Error(`Invalid Context Type : ${context}`);
    }
};

const result1 = testFunction('Acontext') // "a"
const result2 = testFunction('Bcontext') // "b"

操場

但是,它並不是超級安全。 TS 仍將允許此代碼

    switch (context) {
        case "Acontext":
            return bObject; // wrong
        case "Bcontext":
            return aObject; // wrong
        default:
            throw new Error(`Invalid Context Type : ${context}`);
    }

另一種可能性是稍微重構代碼以使用 object 形式的輸入和 output 的簡單映射。

type AorB<T extends Context> = {
  "Acontext": A
  "Bcontext": B
}[T]

const testFunction = <T extends Context>(context: T): AorB<T> => {
  const aObject: A = "a";
  const bObject: B = "b";

  const result = {
    "Acontext": aObject,
    "Bcontext": bObject
  }[context]

  if (!result) throw new Error(`Invalid Context Type : ${context}`)

  return result
};

現在我們沒有類型錯誤並且可讀性也稍好一些。 添加新分支也將更容易。

還有更好的類型安全性的好處,因為這現在會引發錯誤:

const result = {
  "Acontext": bObject,
  "Bcontext": aObject
}[context]

操場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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