当我在打字稿中有一个明确扩展对象的类中的类,然后尝试调用该类的对象方法失败:
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
-prause和 super()
调用,则突然起作用。
我的问题是该代码是从自定义的JSWEET版本中自动化的,而我们仅移动代码库的某些部分。类层次结构中的类不应被映射到Object
,因为extends
在不重新更改JSWEET的情况下无法轻易删除。
我认为您可以说这是打字稿中的错误。可能不是高品位的,但是...: - (
这是因为Object
忽略了它的 this
,并返回一个新的空白对象。打字稿编译该编码的方式(针对ES5环境时(,它最终在Example
中像这样调用Object
:
function Example() {
return Object.call(this) || this;
}
Object.call(this)
的结果是一个新对象,好像您做了{}
。
所以解决方案是...不要那样做。: - (
我的问题是该代码是从自定义的JSWEET版本中自动化的,而我们仅移动代码库的某些部分。类层次结构中的类不应被转移到对象,因为如果不大量更改JSWEET,则无法轻易删除扩展。
ouch。如果您可以定位ES2015 ,则问题消失了,因为这仅与版本TypeScript为ES5及更早创建。如果您不能,恐怕您听起来您想在"打字稿"问题列表上提交问题,并可能使用修复程序进行拉动请求。(我去寻找现有报告,但没有找到。(这与扩展其他内置INS(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
。
提交错误报告后,我被暗示到了一个FAQ条目,该输入涉及扩展Typescript的内置INS:
在ES2015中,返回对象的构造函数隐式将其值替换为Super(...(的任何呼叫者。生成的构造函数代码必须捕获超级(...(的任何潜在返回值并用此替换。
结果,子分类错误,数组和其他人可能不再按预期工作。这是由于以下事实:构造函数在错误,阵列和类似的功能上使用ecmascript 6的new.target来调整原型链。但是,没有办法确保新值的值。在Ecmascript 5中调用构造函数时。
解释类似于T.J.Crowder的答案,加上他们建议另一个其他解决方法:
作为建议,您可以在任何超级(...(调用后立即手动调整原型。
在我的情况下,将 Object.setPrototypeOf(this, Example.prototype);
添加到构造函数中(或说服jsweet这样做(。
但是:
不幸的是,这些解决方法将无法在 Internet Explorer 10 上使用。一个人可以手动从原型将方法复制到实例本身(即fooerror.prototype(,但是原型链本身无法修复。
编辑:我最终使用了此解决方法,因为我发现在我们的JSWEET项目中更容易实现。
编辑2:此解决方法还有其他缺点,因此我们继续使用了一个虚拟班,如接受的答案所述。