TypeScript如何根据接口映射的参数属性推断函数返回类型
解决Web Worker通信中send函数返回类型自动推断问题
要实现根据传入的action自动推断send函数的返回类型,核心是利用TypeScript泛型结合类型映射,将输入的消息类型与对应的返回类型绑定起来。以下是具体实现方案:
步骤1:明确返回消息的类型映射
首先为每个Action定义对应的返回结构,并创建映射关系:
enum Action { Ack = 'ack', Init = 'init' } // 原有的消息定义 interface BaseMessage { action: Action; } interface AckBaseMessage extends BaseMessage { action: Action.Ack; } interface InitBaseMessage extends BaseMessage { action: Action.Init; } interface MessageDataMapping { [Action.Ack]: AckBaseMessage; [Action.Init]: InitBaseMessage; } // 新增:定义每个Action对应的返回结构 interface InitResponse { action: Action.Init; result: { somePropertiesHere: boolean; }; } interface AckResponse { action: Action.Ack; result: { isSuccess: boolean; }; } // 新增:返回类型的映射 type ResponseMapping = { [Action.Init]: InitResponse; [Action.Ack]: AckResponse; }; export type Message = { [K in Action]: MessageDataMapping[K] }[Action];
步骤2:改造send函数为泛型函数
通过泛型参数K绑定传入的action类型,让TypeScript自动推断对应的返回类型:
// 改造send函数,添加泛型约束 async function send<K extends Action>(payload: MessageDataMapping[K]): Promise<ResponseMapping[K]> { return thisWouldBeReturnedFromWebWorker(payload) as Promise<ResponseMapping[K]>; } // 改造工作者函数的返回类型,去掉any async function thisWouldBeReturnedFromWebWorker<K extends Action>(payload: MessageDataMapping[K]): Promise<ResponseMapping[K]> { if (payload.action === Action.Init) { return { action: Action.Init, result: { somePropertiesHere: true } } as ResponseMapping[K]; } return { action: Action.Ack, result: { isSuccess: true } } as ResponseMapping[K]; }
步骤3:验证类型推断效果
现在调用send函数时,TypeScript会根据传入的action自动推断返回结果的结构:
send({ action: Action.Init }).then(response => { // ✅ 类型推断正常:response.result.somePropertiesHere 存在且为boolean console.log(response.result.somePropertiesHere); // ❌ 类型报错:response.result.isSuccess 不存在(因为当前action是Init) // console.log(response.result.isSuccess); }); send({ action: Action.Ack }).then(response => { // ✅ 类型推断正常:response.result.isSuccess 存在且为boolean console.log(response.result.isSuccess); // ❌ 类型报错:response.result.somePropertiesHere 不存在(因为当前action是Ack) // console.log(response.result.somePropertiesHere); });
核心原理说明
- 泛型参数
K:约束为Action的子类型,确保传入的payload只能是对应Action的消息结构。 - 类型映射
ResponseMapping:建立Action到返回结构的一一对应关系,让TypeScript能根据K找到对应的返回类型。 - 类型断言:在
thisWouldBeReturnedFromWebWorker中使用类型断言是因为TypeScript无法自动识别分支中的返回类型与泛型K的绑定,这是合理的类型安全断言。
内容的提问来源于stack exchange,提问作者Mythridium
相关产品推荐
相关产品推荐

