当类型记录中有一个类可以明确扩展对象时,尝试调用该类的Object方法失败:
class Example extends Object {
constructor() {
super();
}
public getHello() : string {
return "Hello";
}
}
let greeter = new Example();
alert(greeter.getHello());错误:greeter.getHello is not a function。为什么会这样呢?如果我删除了extends-clause和super()调用,那么它就突然起作用了。
我的问题是,代码是从自定义的JSweet版本自动生成的,我们只转换了代码库的一部分。不应该转移的类层次结构中的类被简单地映射到Object,因为在不大量更改JSweet的情况下很难删除extends。
发布于 2019-05-07 12:11:09
我认为您可能会认为这是TypeScript中的一个bug。可能不是最重要的,但是.:-)
这是因为Object忽略了用它调用的this,并返回一个新的空白对象。TypeScript编译代码的方式(针对ES5环境时),最终在Example中像这样调用Object
function Example() {
return Object.call(this) || this;
}Object.call(this)的结果是一个新的对象,就像您做了{}一样。
所以解决办法是.别那么做。:-)
我的问题是,代码是从自定义的JSweet版本自动生成的,我们只转换了代码库的一部分。类层次结构中不应该被转移的类被简单地映射到对象,因为如果不大量地更改JSweet,扩展很难被移除。
唉哟。如果您可以针对ES2015+,问题就会消失,因为这只与TypeScript为ES5和更早版本创建的版本有关。如果你做不到,我恐怕你会想要在TypeScript问题清单上提交一个问题,或者用一个修复程序执行一个拉请求。(我去找了一份现有的报告,但没有找到。)这与扩展其他内置(Error,Array)略有不同,因为有一个非常简单的解决方案:忽略extends子句。
或者,正如您在评论中提到的,您可以有一个虚拟类,它什么都不做,比如:
class FauxObject { }然后用它代替Object (class Example extends FauxObject)。
为了详细起见,完整的编译版本是这样的,对Object的调用是用******标记的
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Example = /** @class */ (function (_super) {
__extends(Example, _super);
function Example() {
return _super.call(this) || this; // ******
}
Example.prototype.getHello = function () {
return "Hello";
};
return Example;
}(Object));
var greeter = new Example();
alert(greeter.getHello());在您的情况下,_super就是Object。
发布于 2019-05-08 10:20:53
在提交了一个错误报告后,我被告知一个常见问题条目,用于扩展类型记录内置程序。
在ES2015中,返回对象的构造函数隐式地替代了超级(.)的任何调用者的值。生成的构造函数代码必须捕获超级(.)的任何潜在返回值。用这个代替它。 因此,子类错误、Array等可能不再按预期工作。这是因为构造函数函数用于错误、数组等,使用ECMAScript 6的new.target来调整原型链;但是,在调用ECMAScript 5中的构造函数时,无法确保new.target的值。默认情况下,其他底层编译器通常也有相同的限制。
这一解释类似于T.J.克劳德的回答,此外,他们还推荐了另一种解决办法:
作为建议,您可以在任何超级(.)之后立即手动调整原型。电话。
在我的示例中,这将是将Object.setPrototypeOf(this, Example.prototype);添加到构造函数中(或说服JSweet这样做)。
但
不幸的是,这些解决方案不能在Internet 10和更高版本上使用。可以手动将方法从原型复制到实例本身(即FooError.prototype复制到此),但是prototype链本身无法修复。
编辑:我最终使用了这个解决方法,因为我发现在我们的JSweet项目中更容易实现。
编辑2:这个解决方法还有其他的缺点,所以我们继续使用了一个虚拟类,正如在接受的答案中所简要描述的那样。
https://stackoverflow.com/questions/56022190
复制相似问题