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

如何基于受限类型值重组对象?TypeScript类型问题求助

解决TypeScript联合类型函数参数的类型匹配问题

我正在重构一段代码,需要实现一个函数,根据传入的key(示例中的type)接受对应类型的内容并传递给另一个函数。以下是简化后的问题示例:

type OptionA = { type: 'A'; val: number };
type OptionB = { type: 'B'; val: string };
type Option = OptionA | OptionB;

function give<T extends Option['type']>(type: T, val: Extract<Option, { type: T }>['val']) {
    take({ type, val }); // 此处存在类型警告
}

function take(o: Option) {
    console.log(o);
}

调用give函数时,合法输入会被正确校验,但函数内部的take调用会出现类型警告:

give('A', 1) // 无错误
give('B', 'a') // 无错误

give('A', 'a')
// 警告:类型'string'的参数不能赋给类型'number'的参数。ts(2345)

give('B', 1)
// 警告:类型'number'的参数不能赋给类型'string'的参数。ts(2345)

我尝试简化函数签名,但问题依然存在:

function give<T extends Option>(type: T['type'], val: T['val']) {
  take({ type, val }); // 仍有类型警告
}

问题原因

TypeScript无法自动推断出{ type, val }这个对象严格符合Option联合类型中的某一个成员。虽然调用时的参数校验是正确的,但函数内部构造的对象会被推断为泛型对象类型,而非Option的子类型,因此无法直接传递给接受Option类型的take函数。

解决方案

可以通过类型断言明确构造的对象属于Option联合类型的某一个成员,让TypeScript正确识别类型兼容性:

方案一:直接断言为对应联合成员

function give<T extends Option['type']>(type: T, val: Extract<Option, { type: T }>['val']) {
    const option = { type, val } as Extract<Option, { type: T }>;
    take(option);
}

方案二:基于泛型成员断言

如果使用简化后的泛型签名,可以断言为泛型T:

function give<T extends Option>(type: T['type'], val: T['val']) {
  take({ type, val } as T);
}

这两种方式都能消除类型警告,同时保留调用时的参数类型校验能力,确保type和val的类型始终匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:11:11