如何定义支持任意参数类型的TypeScript函数类型解决回调绑定报错
类型问题解决方案
你遇到的类型报错根源是原有函数类型定义固定了参数范围,且没有和传入的参数列表做关联校验,使用泛型推导可以在不使用any/Function等违禁类型的前提下完美解决,同时还能保留完整的类型校验能力:
class SomeClass {} // 不需要原来的固定参数类型定义,直接给方法加泛型约束 class AwesomeFunctions { // 泛型T约束scope的类型,同时绑定到函数的this指向 // 泛型A约束传入函数的参数列表类型,同时要求后续传入的参数必须和函数参数匹配 public static addClickCallback<T extends object, A extends unknown[]>( element: HTMLElement, func: (this: T, ...args: A) => void, scope: T, ...argArray: A ): void { // 原有校验逻辑 // eslint-disable-next-line no-null/no-null element.onclick = func ? func.bind(scope, ...argArray) : null; } } class AwesomeClass { private bindMe(id: string):void {} private bindMeToo():void {} private bindMeThree(a:string, b: number, c: object): void {} private bindMeFour(clazz: SomeClass): void {} private binder():void { // 所有调用都可以正常通过TS校验,同时会自动校验参数类型是否匹配 AwesomeFunctions.addClickCallback(document.getElementById('...') as HTMLElement, this.bindMeToo, this); AwesomeFunctions.addClickCallback(document.getElementById('...') as HTMLElement, this.bindMe, this, 'param'); AwesomeFunctions.addClickCallback(document.getElementById('...') as HTMLElement, this.bindMeThree, this, 'param', 2, {whoopi: 'goldberg', age: 24, 'actual-age': 'dontcha dare askn!!!'}); AwesomeFunctions.addClickCallback(document.getElementById('...') as HTMLElement, this.bindMeFour, this, new SomeClass()); } }
TS会自动根据你传入的函数推导对应的泛型参数,不需要手动指定,也不需要强制类型转换,同时如果传参和函数参数不匹配还会主动抛出错误,比你原来的类型定义安全性更高。
附带问题解答
你的认知是正确的,该场景下两种写法的作用表现完全一致:
bind方案中你传入的scope就是当前类实例,绑定后的函数运行时this指向就是当前类实例;箭头函数的this继承自外层binder方法的作用域,指向的也是当前类实例,两者this指向完全相同- 两种方案都完成了参数的预置:
bind是通过后续的argArray预先传入参数,箭头函数是直接在函数体内写死要传递给目标方法的参数 - 唯一可感知的差异仅在你需要接收点击事件的Event参数时存在:如果用
bind方案且没有预置完所有参数,Event会作为最后一个参数自动传入绑定的函数;而箭头函数需要你手动声明(e: Event) => this.bindMe('param', e)才能拿到Event参数,如果你不需要用到Event,两者没有任何区别。
内容的提问来源于stack exchange,提问作者aProgger
相关产品推荐
相关产品推荐

