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

TypeScript中如何基于联合类型参数构建类型安全的函数参数?

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

先看给定的联合类型定义:

type Animals =
  | {
      key: 'dog';
      value: { woof: string };
    }
  | {
      key: 'cat';
      value: { meow: number };
    }

我们需要写一个函数fn,要求调用时必须传入与key对应的正确value结构:

  • 合法调用示例:
    fn('dog', { woof: 'woof' });
    fn('cat', { meow: 123 });
    
  • 以下非法调用必须在编译时报错:
    fn('dog', { meow: 'meow' });
    fn('cat', { woof: 'woof' });
    

你之前尝试的写法:

const fn = <T extends Animals>(key: T['key'], value: Extract<T, { key: T['key'] }>['value']) => { /* ... */ }

问题在于TypeScript无法通过这个泛型约束精准推导value的专属类型,最终value还是会被解析成联合类型{ woof: string } | { meow: number },达不到预期的约束效果。

几种可行的解决方案

方案1:泛型约束到联合类型的key,精准推导value

把泛型参数直接约束为Animals中的key类型,再通过Extract提取对应key的value类型:

type AnimalKey = Animals['key'];

const fn = <K extends AnimalKey>(
  key: K,
  value: Extract<Animals, { key: K }>['value']
) => {
  // 这里写函数逻辑
};

这样调用时,TypeScript会根据传入的key自动锁定对应的value类型,非法参数组合会直接触发编译错误。

方案2:使用函数重载

如果觉得泛型写法不够直观,可以用函数重载明确每个合法的参数组合:

// 定义重载签名
function fn(key: 'dog', value: { woof: string }): void;
function fn(key: 'cat', value: { meow: number }): void;
// 实现签名(仅在函数内部可见)
function fn(key: Animals['key'], value: Animals['value']) {
  // 这里写函数逻辑
}

每个重载对应一种合法的调用方式,非法调用会因为匹配不到任何重载签名而报错。

方案3:先构建key-value映射类型

先把Animals联合类型转换成键值对形式的映射类型,再基于这个映射定义函数:

// 把Animals转换成key到value的映射
type AnimalValueMap = {
  [A in Animals as A['key']]: A['value']
};

const fn = <K extends keyof AnimalValueMap>(
  key: K,
  value: AnimalValueMap[K]
) => {
  // 这里写函数逻辑
};

这种方式通过映射类型把联合类型拆解成更直观的键值结构,同样能实现参数类型的精准匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:50:24