TypeScript能否无需类型守卫访问联合类型的非公共字段?
TypeScript 实现联合类型属性的扁平化访问
你想要的这种直接访问联合类型所有属性(不存在的属性自动转为undefined或报错)的原生语法,TypeScript目前是没有的。不过可以通过自定义类型工具,把原联合类型转换成你期望的扁平化类型,从而实现需求。
实现步骤
- 定义一个类型工具,用来把联合类型转换成所有属性的类型联合(包含
undefined,当部分分支没有该属性时):
type FlattenUnion<T> = { [K in keyof (T extends unknown ? T : never)]: T extends { [P in K]?: infer U } ? U : undefined };
- 用这个工具处理你的原联合类型:
type union = { a: string, b: number, c: string, d: number } | {a: string, b: number, c: number } | {a: string, b: string }; // 生成你期望的扁平化类型 type FlattenedUnion = FlattenUnion<union>;
这个FlattenedUnion等价于:
{ a: string; b: number | string; c: string | number | undefined; d: number | undefined; }
- 把变量声明为这个扁平化类型,就能实现你要的访问效果:
const foo: FlattenedUnion = { a: "test", b: 123, c: "abc", d: 456 }; foo.a; // 类型为 string foo.b; // 类型为 number | string foo.c; // 类型为 string | number | undefined foo.d; // 类型为 number | undefined foo.e; // 编译报错(不存在该属性)
类型工具原理
keyof (T extends unknown ? T : never):通过分布式条件类型,获取联合类型所有分支的所有键的集合;- 对于每个键
K,再次通过分布式条件类型,提取所有分支中K属性的类型,若某个分支没有K属性,则自动补充undefined,最终合并为该属性的联合类型。
内容的提问来源于stack exchange,提问作者Ákos Vandra-Meyer
相关产品推荐
相关产品推荐

