簡體   English   中英

如何使 Discriminated Unions 與解構一起工作?

[英]How to make Discriminated Unions work with destructuring?

考慮以下三種類型,其中MainTypeType1Type2並集。 如果kind"kind1"那么data的類型應該是{msg: string}Type2相同

interface Type1 {
    kind: "kind1";
    data: { msg: string };
}
interface Type2 {
    kind: "kind2";
    data: { msg2: string };
}

type MainType = Type1 | Type2;

這是使用它的第一種方法。

function func(obj: MainType) {
    switch (obj.kind) {
        case "kind1": return obj.data.msg;
        case "kind2": return obj.data.msg2;
    }
}

上面的代碼沒有給出錯誤並顯示正確的自動完成。

但是當我們解構obj它會出錯。

function func({kind, data}: MainType) {
    switch (kind) {
        case "kind1": return data.msg;
        case "kind2": return data.msg2;
    }
}

錯誤是

屬性'msg'不存在於類型'{ msg: string; } | { msg2: string; }' '{ msg: string; } | { msg2: string; }'

也許它的一些非常基本的東西。 但我是 ts 的新手,所以我無法了解解構如何改變類型。 請解釋原因,並告訴有什么方法可以解決它。

通過在函數參數級別使用解構,我們松散了kinddata之間的聯系。 因此,按kind切換不會像現在那樣縮小data因為它們處於不同的數據結構中。

我可以說你刪除了kinddata之間的界限,這意味着你真的引入了兩個變量,一個類型為kind1 | kind2 kind1 | kind2和第二個類型為{ msg: string; } | { msg2: string; } { msg: string; } | { msg2: string; } { msg: string; } | { msg2: string; } .

結果我們不再有kind形式的判別kind了。

下面是解構行為的等效代碼:

const f = (t: MainType) => {
  const kind = t.kind // "kind1" | "kind2";
  const data = t.data // {msg: string;} | {msg2: string;}
}

是的,從邏輯角度來看,您的代碼完全沒問題,因為我們知道這些字段之間的關系,所以它應該可以工作。 不幸的是,TS 無法理解界限。

總之- 不幸的是,除非您沒有將類型縮小到聯合的特定成員,否則您不能使用解構,因為它會破壞字段之間的類型關系。


我們可以考慮一些類型保護的解決方法 考慮以下示例:

const isKind1 = (kind: MainType['kind'], data: MainType['data']): data is Type1['data'] 
=> kind === 'kind1'
const isKind2 = (kind: MainType['kind'], data: MainType['data']): data is Type2['data'] 
=> kind === 'kind2'

const f = ({kind, data}: MainType) => {
  if (isKind1(kind, data)) {
    data // is { msg: string }
  }
  if (isKind2(kind, data)) {
    data // is { msg2: string }
  }
}

通過使用類型保護isKind1isKind2我們能夠在這兩個變量之間創建連接。 但問題是我們不能再使用switch ,我們還有更多的代碼,以及在函數中實現的字段關系而不是類型定義,這種方法容易出錯,因為我可以在函數中做不同的關系,然后原始類型正在定義。

明確地說,我正在展示它是可能的,但它不值得,我建議保留原始實現而不破壞。

暫無
暫無

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

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