TypeScript 版本: 2.1.5
自从 TypeScript 2.1(由于 #7574 )以来,构造函数调用的返回值是超类构造函数的返回值。因此,
class Child extends Base {}
会被编译成
function Child() {
return _super !== null && _super.apply(this, arguments) || this;
}
实际行为:
实际上的问题是,尽管示例 ( child
) 不满足其类型 Child
,但 Child
(参见下面的示例)的实现将不会出错,因为 someMethod
并不存在于 child
上。
class Base {
hello = 'base';
constructor() {
return {
hello: 'world'
};
}
}
class Child extends Base { // <-- compiler does not complain
someMethod() {}
}
const child = new Child();
child.someMethod(); // <-- compiler does NOT complain, despite of "someMethod" does not exist on {hello: 'world'}
预期行为:
如果子类构造函数的隐式返回值不是子类的类型,编译器应该对此发出警告。因此,要么像这样强制为子类构造函数显式定义返回值...
class Child extends Base {
constructor() {
super();
return {
someMethod() {},
/* ... inherited members */
}
}
someMethod() {}
}
要么需要扩展返回值( const base = super()
)以满足类型 Child
,或者所有子类成员都必须是可选的。
9条答案
按热度按时间w46czmvw1#
实际问题是,尽管示例(子对象)不满足其类型Child,但Child(见下例)的实现仍然可以成功编译,因为child上不存在someMethod方法。
但问题不在
Child
,而在Base
和Base
中,它们都能正确报告错误。那么请求在Child
中也报告另一个错误是否合理?vqlkdk9b2#
但是问题不在Child,而是在Base,Base正确地报告了错误。那么请求在Child中也报告另一个错误吗?
啊,抱歉,表述不够清楚。这个问题不是关于
Base
类缺少someBaseMethod
成员,而是关于Child
示例缺少someMethod
成员。我已经调整了示例并删除了someBaseMethod
。希望这能澄清实际的问题。6ie5vjzr3#
我认为这是一个我们理解的问题,但由于建模问题存在的困难以及我们预期的相对罕见性,我们决定采取宽松的态度。
我不认为我知道描述这种行为的具体机制,除了在构造签名上进行新的编码。作为一个例子,像这样:
但即使是这样,它也面临着一个问题,即它无法传达返回对象的原型是否适当地进行了调整。
yiytaume4#
CC @justinfagnani for any ideas
anauzrmj5#
但是这还不足以构成编译错误吗?因为tsc在这种情况下已经抛出了异常:
我希望当出现描述的问题时,编译器也会抛出异常。
ep6jt1vc6#
我认为问题在于构造函数被类型化以返回其包含类的示例类型,而不是
this
类型。返回this
的方法似乎可以正常工作:(忽略构造函数中的运行时无限循环 :) )
如果构造函数必须返回一个
this
,那么它将迫使作者要么进行类型转换并说“相信我”,或者做更正确的事情:^ 我看到
Object.create
已经可以正确地推断出像Object.create(A.prototype)
这样的用法的类型,但我不确定让它理解Object.create(new.target.prototype)
具有this
类型的难度有多大。efzxgjgh7#
我想要添加一些更现实的使用案例,用于返回除
this
之外的其他内容,以查看它如何进行类型检查:Function.call
一个类构造函数的问题。zu0ti5jz8#
我看到2.2rc支持
new.target
,但它没有被推断为this
类型。已提交#1384950pmv0ei9#
@DanielRosenwasser ,你觉得我的诊断在这里是否正确?当从构造函数返回时,问题是否应该更改为要求
this
类型?