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

通过唯一属性区分联合类型:TypeScript如何缩小响应类型?

解决TypeScript联合类型函数输入输出类型关联问题

给定通过method字段区分的联合类型:

type Actions = {
  method: "connections",
  request: number,
  response: number,
} | {
  method: "delete",
  request: string,
  response: string,
}

希望编写函数接收对应method的request参数,返回匹配类型的response,但当前定义的泛型函数:

type Fn = <A extends Actions>(a: Pick<A, 'method' | 'request'>) => Pick<A, 'method' | 'response'>; 

调用时无法自动缩小response类型:

const x = fn({ method: "connections", request: 10 })
x.response // 类型为 string | number,而非预期的number

以下是无需再次检查method即可实现类型精准匹配的解决方案:


方案1:通过Extract关联method对应子类型

将泛型约束绑定到method的字面量类型,用Extract从联合类型中提取对应method的子类型,确保输入输出类型严格关联:

type Fn = <M extends Actions['method']>(
  a: Pick<Extract<Actions, { method: M }>, 'method' | 'request'>
) => Pick<Extract<Actions, { method: M }>, 'method' | 'response'>;

方案2:用映射类型重构关联关系

先将Actions转换为以method为键的映射类型,让类型关联更直观:

// 构建method到请求响应类型的映射
type ActionMap = {
  [A in Actions as A['method']]: Omit<A, 'method'>
};

// 定义函数类型
type Fn = <M extends keyof ActionMap>(
  a: { method: M } & { request: ActionMap[M]['request'] }
) => { method: M } & { response: ActionMap[M]['response'] };

效果验证

调用时TypeScript会自动根据method推断出正确的response类型:

const x = fn({ method: "connections", request: 10 });
x.response; // 类型为number(符合预期)

const y = fn({ method: "delete", request: "user-id-123" });
y.response; // 类型为string(符合预期)

原写法问题分析

原泛型A extends Actions的约束过于宽泛,TypeScript无法精准推断出传入参数对应的具体联合成员,导致返回值的response仍保留联合类型。绑定泛型到method字面量后,能强制TypeScript锁定到对应子类型,实现输入输出的类型强关联。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:45:32