如何根据字段类型从TypeScript联合类型中提取指定类型?
解决TypeScript函数根据输入参数精确推断返回类型的问题
当前代码中,sendCommand函数接收OutputActions联合类型参数,但返回值被推断为InputActions联合类型,无法根据传入的command值自动锁定对应的InputAction子类型,导致访问k.token时报错。要实现精确类型推断,可以通过泛型+映射类型来关联输入输出的类型关系:
步骤1:定义类型映射关系
先创建一个映射类型,将command(与action_id值一致)和对应的输入、输出类型绑定:
// 定义命令到对应类型的映射 type ActionMap = { start: { input: InputAction1; output: OutputAction1; }; end: { input: InputAction2; output: OutputAction2; }; };
步骤2:重构sendCommand为泛型函数
利用泛型参数锁定传入的command类型,然后通过映射类型获取对应的返回值类型:
interface OutputAction1 { command: 'start'; params: string; } interface OutputAction2 { command: 'end'; data: string; } interface InputAction1 { action_id: 'start'; token: string; } interface InputAction2 { action_id: 'end'; userData: string; } type ActionMap = { start: { input: InputAction1; output: OutputAction1; }; end: { input: InputAction2; output: OutputAction2; }; }; // 泛型函数,C约束为ActionMap的key(即'start'|'end') const sendCommand = <C extends keyof ActionMap>(action: ActionMap[C]['output']): ActionMap[C]['input'] => { if (action.command === 'start') { return { action_id: 'start', token: '123' } as ActionMap[C]['input']; // 类型断言确保TS识别分支返回类型 } else { return { action_id: 'end', userData: '123' } as ActionMap[C]['input']; } }; // 现在类型推断正常 let k = sendCommand({ command: 'start', params: '' }); k.token; // 正确识别为InputAction1,无报错 let m = sendCommand({ command: 'end', data: '' }); m.userData; // 正确识别为InputAction2,无报错
原理说明
- 泛型参数
C会根据传入的action.command自动推断为具体的命令值('start'或'end')。 ActionMap[C]['output']约束了函数参数必须是对应命令的OutputAction类型,ActionMap[C]['input']则明确了返回值是对应命令的InputAction类型,实现了输入输出类型的精确绑定。- 分支中的类型断言是因为TS无法自动将分支返回值与泛型约束的返回类型关联,手动断言后即可消除类型报错。
内容的提问来源于stack exchange,提问作者Kostya Tresko
相关产品推荐
相关产品推荐

