簡體   English   中英

在 TypeScript 中組合並集和交集類型時的參數類型解析

[英]Param type resolution when combining union and intersection types in TypeScript

這里有3種簡單的類型

type T1 =
  | { letter: 'a'; valueFunc: (prop: number) => void; valueType: number }
  | { letter: 'b'; valueFunc: (prop: string) => void; valueType: string }

type T2 = { base: 'low' }

type T3 = T1 & T2

和 2 個簡單的定義

const var1: T3 = { letter: 'b', base: 'low', valueFunc: (prop) => {}, valueType: 'empty' }

const var2: T3 = { letter: 'a', base: 'low', valueFunc: (prop) => {}, valueType: 0 }

這可以按預期完美運行。 TS 正確評估valueFunc中的prop類型。 但是,如果我向T2添加另一個類型聯合,則 TS 不再能夠解析prop但它仍然可以解析valueType

修改類型

type T1 =
  | { letter: 'a'; valueFunc: (prop: number) => void; valueType: number }
  | { letter: 'b'; valueFunc: (prop: string) => void; valueType: string }

type T2 = { base: 'low' } | {noise: 'high'}

type T3 = T1 & T2

const var1: T3 = { letter: 'b', base: 'low', valueFunc: (prop) => {}, valueType: 'empty' }

const var2: T3 = { letter: 'a', noise: 'high', valueFunc: (prop) => {}, valueType: 0 }

這是為什么? 我錯過了什么?

TypeScript 與有區別的聯合工作得很好

T1是有區別的,因為每個聯合都有letter屬性,而T2沒有。 您有兩種方法可以解決此問題。

第一種方式只需將discriminator器添加到T2 ,例如:

type T2 = { type: '1', base: 'low' } | { type: '2', noise: 'high' }

第二種方式使您的T2聯合更加嚴格。 有關更多說明,請參閱此答案

type T1 =
  | { letter: 'a'; valueFunc: (prop: number) => void; }
  | { letter: 'b'; valueFunc: (prop: string) => void; }


type UnionKeys<T> = T extends T ? keyof T : never;

type StrictUnionHelper<T, TAll> =
  T extends any
  ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;

type StrictUnion<T> = StrictUnionHelper<T, T>

type T2 = StrictUnion<{ base: 'low' } | { noise: 'high' }>

type T3 = T1 & T2

const var1: T3 = { letter: 'b', base: 'low', valueFunc: (prop) => { } } // prop is string

const var2: T3 = { letter: 'a', noise: 'high', valueFunc: (prop) => { } } // prop is number

操場

經驗法則:如果您有一個聯合,其中每個對象都不同並且沒有任何共同點 - 添加鑒別器。

更多解釋

1)

為什么我們使用UnionKeys而不是keyof T

我們也可以使用T extends any 這里的要點是使用條件類型進行分配 為什么 ? 因為當您使用keyof ({a:1}|{b:2})時,您將never不會得到,因為它們不共享公共屬性。 這里

這意味着當您使用時:

type UnionKeys<T> = T extends any ? keyof T : never;

keyof T單獨應用於聯合中的每個元素,而不是僅應用於整個聯合,因為我們在這里使用了T extends any

一般來說,您應該將T extends any - 作為turn on distributivity性和[T] extends [any] - 作為檢查它而不進行分配性。

PS您可以查看我的博客以獲取更多有趣的示例

暫無
暫無

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

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