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

TypeScript条件类型实现回调存储时类型交集错误排查

TypeScript 类型报错:Callback 无法赋值给 Callback<"ok"> & Callback<"error">

我来帮你拆解这个问题:

问题背景

你想要通过泛型和条件类型,把对应类型的回调分别存入storage.ok(接收Record<string, string>参数)和storage.error(接收Error参数)集合,但在调用storage[type].add(callback)时遇到了类型报错,核心疑问是:为什么add方法的参数会被推断成Callback<"ok"> & Callback<"error">这个交集类型?

交集类型的来源分析

这是TypeScript处理联合类型索引访问时的特性:

  • 当你用泛型T extends Mapping['type']作为索引访问storage[type]时,TypeScript没办法在编译期确定type到底是"ok"还是"error",所以它会把storage[type]推断成联合类型:Set<Callback<"ok">> | Set<Callback<"error">>。
  • 对于联合类型的方法调用,TypeScript会要求参数满足所有联合成员方法的参数要求(也就是取参数类型的交集)——因为只有这样,不管联合类型实际是哪一个成员,调用方法都是安全的。所以add方法的参数就变成了Callback<"ok"> & Callback<"error">,而你的Callback<T>只满足其中一种类型的要求,自然会报错。

解决方案

这里有几种可行的修复方式,按需选择:

1. 类型断言(简单直接)

直接告诉TypeScript,storage[type]就是对应Set<Callback<T>>类型:

const storage: Store = { ok: new Set(), error: new Set(), };
function store<T extends Mapping['type']>( type: T, callback: Callback<T> ): void {
  (storage[type] as Set<Callback<T>>).add(callback);
}

2. 条件分支缩小类型(更安全)

通过明确的条件判断,让TypeScript精确推断出当前操作的集合类型:

const storage: Store = { ok: new Set(), error: new Set(), };
function store<T extends Mapping['type']>( type: T, callback: Callback<T> ): void {
  if (type === 'ok') {
    storage.ok.add(callback as Callback<"ok">);
  } else {
    storage.error.add(callback as Callback<"error">);
  }
}

3. 函数重载(最优雅的调用体验)

用函数重载明确每种调用场景的类型,让TypeScript在编译期就能精确匹配:

const storage: Store = { ok: new Set(), error: new Set(), };

// 重载声明
function store(type: 'ok', callback: Callback<'ok'>): void;
function store(type: 'error', callback: Callback<'error'>): void;

// 实现函数
function store(type: Mapping['type'], callback: Callback<any>): void {
  storage[type].add(callback);
}

这样调用store('ok', (data) => {})时,TypeScript会自动推断data是Record<string, string>,调用store('error', (err) => {})时推断err是Error,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:01:06