为什么品牌枚举不能在 Typescript 3 中联合?



我正在尝试使用品牌枚举在 Typescript 3 中获取名义类型(有关此模式的描述,请参阅 TypeScript Deep Behind(。

以下代码在 TS 2.8 和 3.0.3 中都运行良好:

export enum WidgetIdBrand {}
export type WidgetId = WidgetIdBrand & string;
const id:WidgetId = '123' as WidgetId;

但是,在 TS 3.0.3 中,当 WidgetId 与其他一些类型联合时,不会保留 WidgetId。编译器似乎正在折叠(EnumType和字符串(成never,但只有在并集中时才存在

const id2: WidgetId | null = id;
// Type 'WidgetId' is not assignable to type 'null'.

但是,其他类型的工会工作正常:

const id1: WidgetId = id;                   // works
const id2: WidgetId | null = id;            // error
const id3: WidgetId | undefined = id;       // error
const id4: WidgetId | number = id;          // works!?
const id5: WidgetId | boolean = id;         // error
const id6: WidgetId | { kind: 'bar' } = id; // error
const id7: WidgetId | {} = id;              // works!?

有没有办法让品牌枚举在 TS 3 中的工会中发挥作用?

经过一些反复试验,我找到了解决方案。问题似乎是空的品牌枚举被视为扩展number,当与其他类型结合时,number & string崩溃成never

解决方案是将未使用的字符串值添加到品牌枚举中,以便它扩展string(此时可以完全省略品牌枚举(。

以下代码全部有效:

export enum WidgetId { _unused = '¯_(ツ)_/¯'}
const id:WidgetId = '123' as WidgetId;
const id1: WidgetId = id;                   
const id2: WidgetId | null = id;            
const id3: WidgetId | undefined = id;       
const id4: WidgetId | number = id;          
const id5: WidgetId | boolean = id;         
const id6: WidgetId | { kind: 'bar' } = id; 
const id7: WidgetId | {} = id;              

最新更新