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

如何避免TypeScript对对象字面量联合类型进行规范化?

如何让TypeScript推断非规范化的判别式联合类型?

问题场景

给定以下TypeScript函数,我们通过as const断言保留返回对象的字面量类型:

function Foo(num: number) {
  switch (num) {
    case 0: return { type: "Quz", str: 'string', } as const;
    case 1: return { type: "Bar", 1: 'value' } as const;
    default: throw new Error("Unknown discriminant: " + num);
  }
}

TypeScript默认会对判别式联合类型做规范化处理,自动为每个联合成员添加其他分支的属性作为可选undefined类型,最终推断的返回类型为:

function Foo(num: number): 
{ readonly type: "Quz"; readonly str: "string"; readonly 1?: undefined; } |
{ readonly type: "Bar"; readonly 1: "value"; readonly str?: undefined; }

但我们需要的是更简洁的、无冗余可选属性的联合类型:

{ type: "Quz"; str: "string"; } | { type: "Bar"; 1: "value"; }

要求:不手动指定函数返回类型,不提前枚举所有输出分支,仅通过编译器推断得到目标类型。


解决方案

方法一:自定义工具类型过滤冗余属性

通过定义工具类型移除联合类型中值为undefined的可选属性,同时保留原字面量类型约束:

  1. 定义工具类型:
// 移除对象中值为undefined的可选属性,同时将只读属性转为普通属性
type OmitUndefinedOptionalProps<T> = T extends object ? {
  [K in keyof T as T[K] extends undefined ? never : K]: 
    T[K] extends readonly infer U ? U : T[K]
} : T;
  1. 包装原函数并转换返回类型:
type OmitUndefinedOptionalProps<T> = T extends object ? {
  [K in keyof T as T[K] extends undefined ? never : K]: 
    T[K] extends readonly infer U ? U : T[K]
} : T;

const Foo = ((num: number) => {
  switch (num) {
    case 0: return { type: "Quz", str: 'string', } as const;
    case 1: return { type: "Bar", 1: 'value' } as const;
    default: throw new Error("Unknown discriminant: " + num);
  }
}) as unknown as (num: number) => OmitUndefinedOptionalProps<ReturnType<typeof Foo>>;

此时Foo的返回类型会被推断为目标类型,且无需手动编写每个分支的类型定义。

方法二:使用satisfies断言(TypeScript 4.9+)

如果不需要保留属性的只读特性,可以去掉as const,改用satisfies断言确保类型字面量的正确性:

// 定义基础判别式类型,仅做类型检查不影响推断
type DiscriminantBase = { type: string };
function Foo(num: number) {
  switch (num) {
    case 0: return { type: "Quz", str: 'string' } satisfies DiscriminantBase;
    case 1: return { type: "Bar", 1: 'value' } satisfies DiscriminantBase;
    default: throw new Error("Unknown discriminant: " + num);
  }
}

这种方式下,TypeScript会直接推断出非规范化的联合类型,属性为可写状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 03:25:26