TypeScript接口如何定义参数顺序动态切换的onChange回调方法
TypeScript 动态参数顺序回调的类型定义方案
核心原则是将布尔条件属性和回调的参数类型做绑定,通过判别式联合实现类型收窄,不要拆开独立定义两个属性的类型。
推荐方案:判别式联合类型(100%类型安全)
把Props定义为基于xxx值的联合类型,不同xxx取值对应不同的onChange参数签名:
// 替换为你业务中a、b的实际类型 type A = string; type B = number; type Props = | { xxx: true; onChange: (firstArg: A, secondArg: B) => void; } | { xxx: false; onChange: (firstArg: B, secondArg: A) => void; };
这种定义下TS会自动根据props.xxx的判断收窄onChange的类型,你原有的调用逻辑不需要任何修改就可以通过类型校验:
function DemoComponent(props: Props) { const a: A = "示例值"; const b: B = 123; if (props.xxx) { // 此处TS自动推导onChange类型为(a:A, b:B) => void,传参合法 props.onChange(a, b); } else { // 此处TS自动推导onChange类型为(b:B, a:A) => void,传参合法 props.onChange(b, a); } }
如果xxx是可选属性(默认走false逻辑),只需要调整联合中true分支的xxx为可选即可:
type Props = | { xxx?: true; onChange: (firstArg: A, secondArg: B) => void; } | { xxx: false; onChange: (firstArg: B, secondArg: A) => void; };
兜底方案:函数重载签名(类型安全度低)
如果你不需要约束外部调用方必须根据xxx传对应顺序的回调,只需要保证组件内部调用不报错,可以给onChange写重载签名:
interface Props { xxx: boolean; onChange: { (a: A, b: B): void; (b: B, a: A): void; }; }
这种写法的问题是不管xxx是true还是false,两种参数顺序的调用都被允许,无法对调用方做强制约束,只适合临时兼容场景。
不推荐写法
不要把参数直接定义为联合类型:
// 错误示例,完全丢失参数顺序信息 interface BadProps { xxx: boolean; onChange: (a: A | B, b: A | B) => void; }
这种写法虽然不会报类型错误,但是完全丢失了参数位置和类型的对应关系,不管是组件内部还是外部调用都无法获得正确的类型提示。
内容的提问来源于stack exchange,提问作者Lance O
相关产品推荐
相关产品推荐

