簡體   English   中英

基於字符串文字類型參數的變量返回類型

[英]Variable return types based on string literal type argument

我可以根據 TypeScript 1.8 或 2.0 中字符串文字類型參數的值設置變量返回類型嗎?

type Fruit = "apple" | "orange" 
function doSomething(foo : Fruit) : string | string[] {
    if (foo == "apple") return "hello";
    else return ["hello","world"];
}

var test : string[] = doSomething("orange");

錯誤:TS2322:輸入“字符串” string[]' 不能分配給類型 'string[]'。

是的,您可以使用重載簽名來實現您想要的:

type Fruit = "apple" | "orange"

function doSomething(foo: "apple"): string;
function doSomething(foo: "orange"): string[];
function doSomething(foo: Fruit): string | string[]
{
    if (foo == "apple") return "hello";
    else return ["hello", "world"];
}

let orange: string[] = doSomething("orange");
let apple: string = doSomething("apple");

嘗試將doSomething("apple")分配給orange會產生編譯時類型錯誤:

let orange: string[] = doSomething("apple");
 // ^^^^^^
 // type 'string' is not assignable to type 'string[]'

TypeScript Playground 上的現場演示

需要注意的是,確定使用哪個重載簽名必須始終在函數實現中手動完成,並且函數實現必須支持所有重載簽名

TypeScript 中的每個重載沒有單獨的實現,例如在 C# 中。 因此,我發現在運行時加強 TypeScript 類型檢查是一個很好的做法,例如:

switch (foo) {
    case "apple":
        return "hello";
    case "orange":
        return ["hello", "world"];
    default:
        throw new TypeError("Invalid string value.");
}

我有一個更好的方法。 使用泛型然后用作參數的類型(這樣你就不需要手動傳遞泛型,typescript 會自動推斷它)。 然后您可以使用該類型並選擇正確的返回類型。

type Fruit = 'apple' | 'orange';
function doSomething<P extends Fruit>(foo: P): ({ apple: string; orange: string[] })[P] {
  if (foo === 'apple') return 'hello';
  return ['hello','world];
}
const x: string = doSomething('apple');
const y: string[] = doSomething('orange');

通過這種方式,您可以根據自動傳遞的參數更改函數的返回類型。

是的,你可以。 您只需要使用instanceof測試您的test變量。 然后打字稿將限制類型。

type Fruit = "apple" | "orange" 
function doSomething(foo: Fruit): string | string[] {
    if (foo == "apple") return "hello";
    else return ["hello","world"]
}

// here the type is still inferred as: string | string[]
var test = doSomething("orange");

if (test instanceof String) {
    // TypeScript knows test is type: string
    doSomethingWithString(test);
} else {
    // TypeScript knows test is type: string[]
    doSomethingWithStringArray(test);
}

function doSomethingWithString(input: string) {}
function doSomethingWithStringArray(input: string[]) {}

更新

您可能只想使該方法通用。

function doSomething<T>(foo: Fruit): T {
    if (foo == "apple") return "hello";
    else return ["hello","world"]
}

var test1 = doSomething<string>("apple");
var test2 = doSomething<string[]>("orange");

或者另一種選擇是將流程反轉為這樣的:

type Fruit = "apple" | "orange" 
function doSomething(foo: Fruit): void {
    if (foo == "apple") 
        doSomthingWithString("hello");
    else 
        doSomethingWithStringArray(["hello","world"]);
}

function doSomethingWithString(input: string) {}
function doSomethingWithStringArray(input: string[]) {}

更新

實際上,我相信John White的答案要好得多。

暫無
暫無

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

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