正如this blog post和这篇堆栈溢出文章中所述,可以按如下方式使对象可调用:
class Callable extends Function {
constructor() {
super();
var closure = function (...args) { return closure._call(...args) }
return Object.setPrototypeOf(closure, new.target.prototype)
}
_call(...args) {
console.log(this, args)
}
}
然而,这会导致CSP(Content-Security-Policy)的问题,比如在Chrome扩展中运行时。可以删除extends Function
和super()
调用,但这会导致类型错误。对于我的用例,不幸的是,我不能忽略这一点。如果有一种方法可以覆盖类型错误(例如,使用JSDoc),那也可以工作。
示例用法应该如下所示:
class Pipeline extends Callable {
_call(...args) {
// Override _call method here
}
}
// Create new pipeline
const pipe = new Pipeline();
// Call the pipeline
// NOTE: This is where the type error happens if the class is not inherited from `Function`. Something along the lines of:
// This expression is not callable. Type 'Pipeline' has no call signatures.
const result = pipe("data");
任何帮助将不胜感激。
1条答案
按热度按时间hgb9j2n61#
TypeScript目前并没有对
class
的constructor
方法返回值时发生的情况进行建模。microsoft/TypeScript#27594上有一个功能请求来支持这一点,但目前TypeScript只会将类示例类型识别为具有其声明的成员,JavaScript不允许你声明类示例的调用签名。因此,即使在运行时,Callable
子类的示例由于返回覆盖和原型杂耍而可调用,TypeScript也无法看到它。如果你使用的是TypeScript文件而不是JSDoc,我可能会建议将所需的调用签名merging到
Callable
接口中,如下所示:你可以在工作中看到:
Playground链接到TS代码
不幸的是,您不能在JSDoc中定义
interface
(请参阅microsoft/TypeScript#33207上的特性请求),虽然这可能适用于多个文件或不同格式,但我将忘记这种方法。相反,您可以使用类型Assert或等效的JSDoc来告诉编译器
Callable
的类型是这意味着它有一个构造签名,返回一个带有
_call
方法的可调用对象。它看起来像这样:您可以验证它是否有效:
Playground链接到JSDoc注解的JS代码
所以这是一种适用于JSDoc的方法。我不打算评论让TypeScript支持可调用类示例的总体目标是否值得追求,除了说这样的事情可能会导致大多数JavaScript/TypeScript用户都不会预料到的令人惊讶的边缘情况行为。显然,用例将推动这样的决定,但仍然应该谨慎行事。