Javascript 子类中带有参数的回调

Javascript 子类中带有参数的回调,javascript,typescript,function,oop,callback,Javascript,Typescript,Function,Oop,Callback,我的一个TypeSript函数有一些问题。我希望这不是一个绝对愚蠢的问题,但我相信我试图做的应该在理论上可行 这是我问题的简化版本。我希望它能显示问题发生的地方(原来的代码太多了) 问题发生在代码的最后一行。log函数是类型为a的回调函数。我想用类型为B的属性来调用它。理论上,这应该是可行的,因为B扩展了A。但它显示了以下错误: Argument of type '(ev: B) => void' is not assignable to parameter of type '(ev: A

我的一个TypeSript函数有一些问题。我希望这不是一个绝对愚蠢的问题,但我相信我试图做的应该在理论上可行

这是我问题的简化版本。我希望它能显示问题发生的地方(原来的代码太多了)

问题发生在代码的最后一行。
log
函数是类型为
a
的回调函数。我想用类型为
B
的属性来调用它。理论上,这应该是可行的,因为
B扩展了A
。但它显示了以下错误:

Argument of type '(ev: B) => void' is not assignable to parameter of type '(ev: A) => void'.
  Types of parameters 'ev' and 'ev' are incompatible.
    Property 'addr' is missing in type 'A' but required in type 'B'.(2345)
input.tsx(13, 5): 'addr' is declared here.
我不想在函数中强制转换我的
ev
参数。我希望你明白问题所在,我的目标是什么


祝你愉快。

这是一个正确的错误,与逆变有关

如果将
log
的参数类型定义为
A
,则定义为:

抽象类A{
// ...
log(ev:A){console.log(ev.name)};
//...
}
您可以从以下位置调用该函数:

设b=新b(“1”、“2”);
b、 日志(b);//工作正常,因为'B'还有属性'name`
你有充分的例子

但当传递完整功能时,它与
(ev:B)=>void
,并不是相反的。例如,满足签名
(ev:B)=>void
的函数可以如下所示:

功能(ev:B){
console.log(ev.addr);//特定于B,类型为A的输入参数将中断!
}

如果您在内部传递
A
类型的
ev
,此函数将中断,因为
A
不包含属性
addr
,只包含
B
。这就是为什么typescript不允许您这样做。

我想调用传递给
log
的函数作为回调。如果我将
log
的参数改为对象而不是函数,它就不再是回调。因此它必须是一个函数。您错过了这一点-两个类上的
日志
回调的有效签名都是
(ev:a)=>void
。然后,您可以在
B
实现中将
B
实例传递给它。对于接受回调并向其提供对象本身的方法,您到底想要什么?假设您可以调用该方法,那么您已经有了对该对象的引用。如果需要的话,您可以调用
b(((uu:any)=>console.log(b.addr))
。对于对象来说,接受将使用同一对象调用的回调似乎有点多余。除非它不是同一个实例,而是同一类的不同实例,但是调用
instance1.log((thisWillBeInstance2=>{})
“理论上,这应该是可行的,因为B扩展了a”-否。
log
方法允许传递
B
实例而不是
a
实例,但不允许回调声明它只接受
B
实例,而不接受任何
a
。请向我们展示
log
的实际实现,以便我们可以推荐正确的键入方法信息技术
Argument of type '(ev: B) => void' is not assignable to parameter of type '(ev: A) => void'.
  Types of parameters 'ev' and 'ev' are incompatible.
    Property 'addr' is missing in type 'A' but required in type 'B'.(2345)
input.tsx(13, 5): 'addr' is declared here.