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

TypeScript中如何为对象键不相交联合函数定义返回类型?

如何为属性不相交联合函数定义TypeScript返回类型

要让disjointUnion函数的返回类型能被精确推导,我们可以借助TypeScript的映射类型、条件类型,针对不同类型的键构造对应的结果类型。核心思路是区分三类键:仅存在于第一个对象的键、仅存在于第二个对象的键、两个对象共有的键,分别为它们生成匹配的类型结构。

步骤1:定义辅助类型

先提取三类键的类型,并构造对应部分的对象结构:

// 提取两个对象的公共键
type CommonKeys<T, U> = keyof T & keyof U;
// 提取仅在第一个对象中存在的键
type OnlyTKeys<T, U> = Exclude<keyof T, keyof U>;
// 提取仅在第二个对象中存在的键
type OnlyUKeys<T, U> = Exclude<keyof U, keyof T>;

// 构造返回类型:合并三类键对应的结构
type DisjointUnionResult<T extends Record<string, any>, U extends Record<string, any>> =
  // 仅T有的键,保留原键和类型
  { [K in OnlyTKeys<T, U>]: T[K] } &
  // 仅U有的键,保留原键和类型
  { [K in OnlyUKeys<T, U>]: U[K] } &
  // 公共键:生成带0/1后缀的键,对应原对象的类型
  { [K in CommonKeys<T, U> as `${string & K}0`]: T[K] } &
  { [K in CommonKeys<T, U> as `${string & K}1`]: U[K] };

// 可选:将交叉类型合并为单一对象类型(优化类型显示)
type Merge<T> = { [K in keyof T]: T[K] };

步骤2:修改函数的返回类型

将函数的返回类型指定为Merge<DisjointUnionResult<T, U>>,同时调整内部的类型断言以适配类型推导:

export function disjointUnion<
  T extends Record<string, any>,
  U extends Record<string, any>
>(obj1: T, obj2: U): Merge<DisjointUnionResult<T, U>> {
  const seenKeys = new Set<string>();
  // 内部用最终返回类型做断言
  const result = {} as Merge<DisjointUnionResult<T, U>>;

  for (const k of Object.keys(obj1)) {
    result[k as keyof typeof result] = obj1[k];
    seenKeys.add(k);
  }

  for (const k of Object.keys(obj2)) {
    if (!seenKeys.has(k)) {
      result[k as keyof typeof result] = obj2[k];
      continue;
    }

    // 处理重复键,添加索引后缀
    const key0 = `${k}0` as keyof typeof result;
    const key1 = `${k}1` as keyof typeof result;
    result[key0] = result[k as keyof typeof result];
    result[key1] = obj2[k];
    delete result[k as keyof typeof result];
  }

  return result;
}

测试类型推导

现在测试你的示例代码,obj3的类型会被正确推导为{ job0: string; job1: string; age: number }:

const obj3 = disjointUnion({ job: "developer", age: 30 }, { job: "teacher" });
// 鼠标悬停obj3可查看类型:{ job0: string; job1: string; age: number }

说明

  • 辅助类型通过Exclude和keyof区分不同类型的键,用as关键字重映射公共键为带后缀的形式。
  • Merge类型的作用是把交叉类型(A & B & C)合并成单一对象类型,让类型显示更直观,不影响类型检查逻辑。
  • 函数内部的as keyof typeof result是因为TypeScript无法在循环中自动推断键的合法性,需要手动断言,但外部的返回类型是完全精确的。

内容的提问来源于stack exchange,提问作者Adam B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:17:13