簡體   English   中英

為什么Typescript推斷'never'而不是交集類型?

[英]Why does Typescript infer 'never' instead of intersection type?

給出以下示例:

interface Data {
    name: string;
    value: number;
}

const data :Data = {
    name: 'name',
    value: 1,
}

const updateValue = (key: keyof Data, value: string | number): void => {
    data[key] = value;
};

鏈接到ts-playgound

Typescript顯示以下錯誤:

Type 'string | number' is not assignable to type 'string & number'.
  Type 'string' is not assignable to type 'string & number'.
    Type 'string' is not assignable to type 'number'.

這是清楚易懂的。 但是,如果我將一個聯合類型添加到接口,如下所示:

type MultiType = 'x' | 'y';

interface Data {
    name: string;
    value: number;
    multiType: MultiType | null;
}

const data :Data = {
    name: 'name',
    value: 1,
    multiType: null,
}

const updateValue = (key: keyof Data, value: string | number): void => {
    data[key] = value;
};

鏈接到ts-playgound

我收到以下錯誤:

Type 'string | number' is not assignable to type 'never'.
  Type 'string' is not assignable to type 'never'.

如果我使用交集類型string & number & MultiType但是它也接受never ,那么Typescript接受它。

這似乎與我不一致。 這可能是個錯誤嗎?

string & number等於neverstring & number & (MultiType | null) 沒有值既是string又是number ,因此沒有值滿足string & numberstring & number & AnythingElse

現在,后者明確地減少到never因為它包含這些等價到never類型的聯合,這樣做真的很難看。 具體來說,編譯器將交叉點分布在聯合上,因此

string & number & ('x' | 'y' | null)

(string & number & 'x') | (string & number & 'y') | (string & number & null)

這種類型對人們來說並不是特別有啟發性,因此編譯器會檢查每個聯合組成部分是否等同於never ,並將類型減少為

never | never | never

這只是

never

如你所見。


那么為什么string & number本身不會立即減少到never 最初的想法是,它可以幫助人們了解代碼中的錯誤來自哪里,因為string is not assignable to number更具啟發性, string is not assignable to never

不幸的是,雖然string & number 相當於 never分配給它的值,但在TS3.5及更低版本中,編譯器並不總是將它們視為相同,這是令人困惑的。

因此看起來,從TS3.6開始, string & number這樣的空交叉將never明確地減少到 一旦TS3.6發布,你的上述代碼在兩種情況下的行為都相同,你將獲得string | number is not assignable to never string | number is not assignable to never錯誤。


好的,希望有所幫助; 祝好運!

兩件事情 :

  • TypeScript不接受string | number合乎邏輯的 string | number作為value參數的類型,因為以下所有內容:

    • string | number string | number不能賦值給string因為如果key'name'number不能賦值給string

    • string | number string | number不能分配給number因為如果key'value' ,則string不能分配給number (在第一個示例中,兩者都已經為真)

    • string | number string | number不能分配給MultiType | null MultiType | null因為numberstring都不能賦值給'x' | 'y' | null 'x' | 'y' | null 如果key'multiType''multiType' 'x' | 'y' | null

但是出於某種原因,在你的第一個例子中,TypeScript只是在第一個“錯誤”的情況下停止並給你這個錯誤(即使已經有兩個錯誤了)。

在第二種情況下,您可能已經看到了相同的錯誤消息,因為類型的不兼容性仍然存在,似乎推理更深入並且告訴您問題比這更深。 至於為什么錯誤消息的格式是這樣的,我真的不知道,我想這將需要更深入地了解編譯器如何在這里推斷出事物。 最后,編譯器是正確的,但錯誤消息可能更清楚。


對於您的第二個問題, never類型的文檔說:

never類型是每種類型的子類型,並且可分配給每種類型

因此,您可以將value指定為never類型,並將其分配給您的data 因為它永遠不會發生。

暫無
暫無

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

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