Typescript:重写超类方法而不需要知道超类方法签名
以下是我如何可靠地重写普通 JS 中的方法,而不关心名称或参数数量或返回值:
import EventEmitter from 'events'
// console.log event + arguments every time this emitter emits anything.
// Just an example.
class LogEmitter extends EventEmitter {
emit(...args) {
console.log('emit', ...args)
return super.emit(...args)
}
}
但在 TypeScript 中,我听到抱怨:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(...args) { // Rest Parameter 'args' implicitly has an any[] type
console.log('emit', ...args)
return super.emit(...args) // Expected at least 1 arguments, but got 0 or more.
}
}
我不确定如何告诉 TypeScript 这是可以的。我不想知道有关我要重写的方法的签名的任何信息,只需打印您传递的任何参数即可。意味着如果/当超类签名发生更改时,我不必更新我的签名,理想情况下,我将有一种方法来键入它,该方法适用于我重写的所有方法,也许有一个例外,告诉它要复制哪个方法名称签名来自.
像这样的东西:
...args
的类型应该与super.emit
的Parameters
相同
但是我的新手尝试这不是有效的语法:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(...args: Parameters<super.emit>) { // 'super' can only be referenced in members of derived classes or object literal expressions.
console.log('emit', ...args)
return super.emit(...args)
}
}
我的解决方法是 any
所需的第一个参数:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(type: any, ...args: any[]) {
console.log('emit', type, ...args)
return super.emit(type, ...args)
}
}
但我认为这更像是修补症状,因为现在此类报告的签名不太准确。我觉得有一个更好的解决方案,可以自动为emit
提供正确的签名,而无需我从super.emit
复制它。
我该如何做完美地输入此内容,而无需了解有关 super.emit
签名的任何信息?
Here's how I would reliably override a method in vanilla JS without caring about names or number of arguments, or the return value:
import EventEmitter from 'events'
// console.log event + arguments every time this emitter emits anything.
// Just an example.
class LogEmitter extends EventEmitter {
emit(...args) {
console.log('emit', ...args)
return super.emit(...args)
}
}
But in TypeScript, I hear complaints:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(...args) { // Rest Parameter 'args' implicitly has an any[] type
console.log('emit', ...args)
return super.emit(...args) // Expected at least 1 arguments, but got 0 or more.
}
}
I'm not sure how to tell TypeScript that this is ok. I don't want to know anything about the signature of the method I'm overriding, just print whatever arguments you're passed. Means I don't have to update my signature if/when the superclass signature changes, and ideally I would have one way to type this that would work for all methods I override, with maybe an exception of telling it which method name to copy the signature from.
Something like:
The type of
...args
should be whatever theParameters
are tosuper.emit
But my newbie attempt at this isn't valid syntax:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(...args: Parameters<super.emit>) { // 'super' can only be referenced in members of derived classes or object literal expressions.
console.log('emit', ...args)
return super.emit(...args)
}
}
My workaround is to any
the required first argument:
import { EventEmitter } from 'events'
class LogEmitter extends EventEmitter {
emit(type: any, ...args: any[]) {
console.log('emit', type, ...args)
return super.emit(type, ...args)
}
}
But I think this is more like patching symptoms, since now this class reports a less accurate signature. I feel like there's a better solution that gives the correct signature for emit
automatically without me having to copy it from super.emit
.
How can I type this perfectly without having to know anything about the signature of super.emit
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不幸的是,Typescript 不(从 TS4.1 开始)上下文类型 子类成员由超类(或实现的接口)中的类似成员组成。有很多类似的 GitHub 问题,但我认为这种特殊情况的规范问题是 microsoft/ TypeScript#23911。目前,您所能做的就是“修补症状”:
作为一种解决方法,如果您想引用超类,则需要通过名称 (
EventEmitter
) 显式执行此操作,而不是通过 < code>super,并且您可以使用 查找类型以获取emit
方法:Playground 代码链接
Unfortunately, Typescript does not (as of TS4.1) contextually type subclass members by the analogous members in super classes (or implemented interfaces). There are a bunch of similar GitHub issues, but I think the canonical one for this particular situation is microsoft/TypeScript#23911. For now, all you can do is "patch symptoms":
As a workaround, if you want to refer to the super class, you will need to do so explicitly by name (
EventEmitter
) and not bysuper
, and you can use a lookup type to get theemit
method:Playground link to code
typeof fn
允许您获取函数的类型,因此parameters&lt; type eventemitter.prototype.emit&gt;
应该使事物工作。typeof fn
lets you get the type of a function, soParameters<typeof EventEmitter.prototype.emit>
should get things working.