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
相关产品推荐
相关产品推荐

