簡體   English   中英

TypeScript 中的類型轉換和條件返回類型

[英]Type conversions and conditional return types in TypeScript

我正在嘗試在 TypeScript 中的自定義類型之間進行轉換並使用條件返回類型。 但是,TS 不會讓我,因為以下不編譯:

type AString = { a: string };
type ANumber = { a: number };
type A<T> = T extends string ? AString : ANumber;
function isANumber(x: any): x is ANumber {
    return x && typeof x.a === "number";
}
function isAString(x: any): x is AString {
    return x && typeof x.a === "string";
}

type BString = { b: string };
type BNumber = { b: number };
type B<T> = T extends string ? BString : BNumber;

function a2b<T>(a: A<T>): T extends string ? BString : BNumber {
    if (isAString(a)) return { b: a.a } as BString;
    if (isANumber(a)) return { b: a.a } as BNumber;
}

有人抱怨函數末尾缺少 return,TS 可能知道,但這不是我的痛點。 更重要的是,無論是BString也不BNumber可以被分配到T extends string ? BString : BNumber T extends string ? BString : BNumber 更令人困惑的是,兩者都不能分配給B<T> 我錯過了條件類型的什么?

PS:使用聯合類型可以解決這個例子中的編譯器錯誤,但在我的實際代碼中不會。

問題是打字稿不能使isAString(a)等價於檢查T extends string邏輯跳轉。 它縮小了變量a的定義而不是泛型T 它仍然認為T可能是因為存在,所以它抱怨返回BStringBNumber分別,因為它不知道你正在返回正確的。

你的as BString as BNumberas BNumber聲明實際上並不是必需的,因為打字稿已經知道它在第一種情況下處理{b: string} ,在第二種情況下處理{b: number} 它未能實現的跳躍是這些類型與T有任何關系。

關閉它的最簡單方法是在兩種情況下都使用as B<T>

另一個簡單的解決方案是讓您的返回類型直接依賴於它可以從T推斷出的值。

function a2b<T extends AString | ANumber>(a: T): {b: T['a']} {
    return { b: a.a };
}

如果泛型T直接描述變量a那么打字稿可以做出更好的推斷,並且會理解如果a是 x 而不是T必須是 x。 所以我盡量讓泛型適用於整個變量。 Typescript 並不是最擅長逆向工作。

盡管如此,我仍然無法在這里找到一個非常好的解決方案。 它只是不喜歡extends 如果我說T extends AString | ANumber T extends AString | ANumber並反向工作以獲取返回類型的stringnumber ,將AType定義為T['a']工作正常,但是如果ATypeT extends AString ? string : number T extends AString ? string : number然后它會中斷。 游樂場鏈接

它與extends真正含義有關,文字字符串和文字數字擴展了字符串和數字。

看看這個錯誤,我想你會理解這個問題:

function a2b<T>(a: A<T>): {b: T} {
    if (isAString(a)) return { b: a.a }; // error TS2322: Type 'string' is not assignable to type 'T'.
 // 'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.
    if (isANumber(a)) return { b: a.a };
}

所以我們知道aa是一個string並且T extends string ,但我們仍然不知道aa可以分配給T因為你可能有這樣的情況Tsome string的文字some stringa{a: "other string"}

暫無
暫無

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

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