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

TypeScript中如何实现不含unknown的类型互斥?

TypeScript实现{value: T}与{error: Error}的互斥类型

问题根源

你之前的写法type MaybeExclusive<T> = { value: T } | { value?: never, error: Error }之所以会出现value类型不确定的情况,是因为value?: never仅将value标记为可选的never类型,但TypeScript未明确排除该属性在另一个分支中的存在,导致类型收窄不彻底。

解决方案1:明确互斥的联合分支

直接在每个联合分支中显式排除另一个属性,确保两个分支严格互斥:

type MaybeExclusive<T> = 
  | { value: T; error?: never } 
  | { value?: never; error: Error };
  • 第一个分支:存在value: T,同时将error标记为可选的never(无法赋值)
  • 第二个分支:存在error: Error,同时将value标记为可选的never(无法赋值)

这种写法既能保证两个类型互斥,又能让TypeScript正确进行类型收窄:

// 合法实例
const success: MaybeExclusive<string> = { value: "操作成功" };
const failure: MaybeExclusive<string> = { error: new Error("操作失败") };

// 非法实例(TypeScript会报错)
const invalid: MaybeExclusive<string> = { value: "冲突", error: new Error("同时存在两个属性") };

解决方案2:通用互斥类型工具

如果需要复用这种互斥逻辑,可以封装一个通用的Exclusive类型工具:

type Exclusive<T, U> = 
  | (T & Record<keyof U, never>) 
  | (U & Record<keyof T, never>);

// 基于通用工具生成目标类型
type MaybeExclusive<T> = Exclusive<{ value: T }, { error: Error }>;

这个工具通过交叉Record<keyof U, never>,直接禁止另一个类型的所有属性存在,实现更严格的互斥约束。

类型收窄使用示例

在实际代码中,通过简单的存在性检查即可让TypeScript自动收窄类型:

function processResult<T>(result: MaybeExclusive<T>) {
  if ("error" in result) {
    // 此处result被收窄为{ error: Error; value?: never }
    console.error("错误信息:", result.error.message);
    return;
  }
  // 此处result被收窄为{ value: T; error?: never }
  console.log("返回值:", result.value);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:45:21