You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中获取联合类型的兼容公共属性?

TypeScript中获取联合类型的兼容公共属性

核心需求

需要实现类型工具CommonKeys<T>,提取联合类型T中满足以下条件的属性键:

  1. 键名存在于联合的所有成员类型中;
  2. 存在有效值可以同时赋值给该键在所有联合成员中的类型(即该键的类型交叉不为never)。

例如:

type TestUnion = {a: number, b: number, c: string} | {a: number, b: string};
type OnlyA = CommonKeys<TestUnion>;
// 期望OnlyA的类型为 "a"(仅a属性的类型在所有成员中兼容,b的类型交叉为number & string = never,无有效值)

更广泛场景:判别式联合的属性更新

基于上述核心需求,希望实现一个函数,根据判别式联合的判别字段,动态限制可更新的属性范围:判别字段的范围越小(越具体),可更新的属性越多。

示例代码:

type Foo = {kind: "foo", id: `foo_${string}`, name: string, age: number}
type Bar = {kind: "bar", id: `bar_${string}`, name: string, height: number}

type Anyone = Foo | Bar

// 期望CommonProps<T>提取T的兼容公共属性,再用Partial包装
function updateSomeone<T extends Anyone["kind"]>(kind: T, patch: Partial<CommonProps<Extract<Anyone, {kind: T}>>>) {}

function outer(foo: Foo) {
  // 已知为Foo类型,允许更新所有属性
  updateSomeone(foo.kind, {id: "foo_2", name: "test", age: 45})
}

function outer2(fooOrBar: Foo | Bar) {
  // @ts-expect-error id不允许:没有值能同时满足Foo["id"]和Bar["id"]的类型要求
  updateSomeone(fooOrBar.kind, {name: "test", id: "foo_2"})
}

解决方案

实现CommonKeys和CommonProps类型工具

// 获取联合类型中所有成员共有的键名
type SharedKeys<T> = keyof T;

// 筛选出键名对应的属性类型交叉不为never的兼容公共键
type CommonKeys<T> = {
  [K in SharedKeys<T>]: 
    // 提取联合中所有成员的K属性类型,取交叉
    (T extends { [key in K]: infer U } ? U : never) extends never 
      ? never 
      : K;
}[SharedKeys<T>];

// 提取联合类型的兼容公共属性
type CommonProps<T> = Pick<T, CommonKeys<T>>;

验证效果

  1. 核心需求示例:
type TestUnion = {a: number, b: number, c: string} | {a: number, b: string};
type OnlyA = CommonKeys<TestUnion>; // 类型为 "a",符合预期
  1. 判别式联合场景:
  • 当调用updateSomeone("foo", ...)时,Extract<Anyone, {kind: "foo"}>为Foo,CommonProps<Foo>即Foo本身,因此Partial<Foo>允许更新所有属性;
  • 当调用updateSomeone(fooOrBar.kind, ...)时,Extract<Anyone, {kind: T}>为Foo | Bar,CommonKeys<Foo | Bar>仅保留"name"(id的类型交叉为never,kind的类型交叉也为never),因此patch仅允许传入name属性,传入id会触发TypeScript错误,符合预期。

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:50:08