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

TypeScript条件类型构建:柯里化函数的消息数据类型约束问题

解决思路与实现方案

要实现这个类型安全的柯里化函数,核心是让TypeScript根据你传入的消息名称,自动推断出对应的数据类型。我们可以通过联合类型 + 泛型约束 + 条件类型提取来达成目标,具体步骤如下:

1. 统一消息类型集合

首先把你的One和Two类型合并成一个联合类型,这样我们能统一处理所有消息的名称和对应数据的映射关系:

type One = { name: "OneMessage"; data: { name: string; } }
type Two = { name: "TwoMessage"; data: { lastName: string; } }

// 合并所有消息类型为联合类型
type Messages = One | Two;

2. 定义泛型柯里化函数

接下来利用TypeScript的泛型和类型提取工具,让函数的第二个参数类型自动关联第一个参数的消息名称:

const genericFN = <T extends Messages['name']>(message: T) => 
  // 从联合类型中提取对应name的消息,再取其data类型
  (data: Extract<Messages, { name: T }>['data']) => 
    ({ message, data });

关键逻辑解释

  • <T extends Messages['name']>:约束第一个参数只能是所有消息类型中定义的name值(也就是"OneMessage"或"TwoMessage"),同时让TypeScript捕获到你传入的具体名称。
  • Extract<Messages, { name: T }>:从联合类型Messages中筛选出name属性等于T的那个具体消息类型。比如当T是"TwoMessage"时,会提取出Two类型。
  • Extract<...>['data']:拿到筛选后的消息类型的data属性类型,作为第二个函数的参数类型约束。

3. 测试效果

现在调用函数时,TypeScript会自动根据你传入的消息名称提示对应的数据结构:

// 传入"TwoMessage"后,返回的函数仅接受{ lastName: string }类型
const createTwoMessage = genericFN("TwoMessage");
createTwoMessage({ lastName: "Doe" }); // ✅ 类型正确
createTwoMessage({ name: "John" }); // ❌ 报错:类型不匹配

// 传入"OneMessage"后,返回的函数仅接受{ name: string }类型
const createOneMessage = genericFN("OneMessage");
createOneMessage({ name: "John" }); // ✅ 类型正确
createOneMessage({ lastName: "Doe" }); // ❌ 报错:类型不匹配

扩展性说明

如果后续需要新增其他消息类型,只需要把新类型加入Messages联合类型即可,函数无需任何修改就能自动支持新的消息名称和对应数据类型:

type Three = { name: "ThreeMessage"; data: { age: number; } }
type Messages = One | Two | Three; // 新增Three类型

const createThreeMessage = genericFN("ThreeMessage");
createThreeMessage({ age: 30 }); // ✅ 自动支持新类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:45:27