如何将参数绑定到TypeScript可辨识联合的特定成员?
如何实现可辨识联合类型的参数绑定
要实现actionKind和params的严格绑定,你可以通过泛型结合Extract工具类型来关联两个参数的类型,确保它们始终对应可辨识联合中的同一个成员。
正确实现代码
type BaseAction = { foo: string; bar: string; }; type ActionA = BaseAction & { kind: 'a'; params: Record<string, never> }; type ActionB = BaseAction & { kind: 'b'; params: { baz: string } }; type Action = ActionA | ActionB; // 修正后的函数 function performAction<K extends Action['kind']>( actionKind: K, params: Extract<Action, { kind: K }>['params'] ) { console.log(actionKind, params); } // 符合预期的调用(正常通过编译) performAction('a', {}); performAction('b', { baz: '1234' }); // 不符合预期的调用(编译报错,符合需求) performAction('a', { baz: '1234' }); // 错误:对象文字可以只指定已知属性,并且“baz”不在类型“Record<string, never>”中 performAction('b', {}); // 错误:缺少属性“baz”
原理说明
- 泛型约束
K:将K约束为Action['kind'](即'a' | 'b'),确保传入的actionKind只能是联合类型中定义的合法kind值。 Extract工具类型:Extract<Action, { kind: K }>会根据当前传入的K值,从Action联合类型中精准提取出对应kind的成员类型(比如当K='a'时,提取出ActionA)。- 关联
params类型:通过Extract<...>['params']获取对应成员的params类型,这样params就会严格绑定到当前actionKind对应的类型上,实现参数间的一对一关联校验。
为什么之前的泛型写法无效
你之前尝试的T extends Action泛型写法之所以没效果,是因为TypeScript会将T推断为整个Action联合类型(ActionA | ActionB),导致actionKind和params仍然是各自的联合类型,无法建立一对一的绑定关系。而通过针对kind单独做泛型约束,再提取对应成员的方式,就能强制两个参数属于同一个联合成员。
内容的提问来源于stack exchange,提问作者Maja Cieślak
相关产品推荐
相关产品推荐

