TypeScript版本: 2.7.0-dev.20171226
代码
class A {
x: {y: string} = {y: 'y'};
}
class B extends A {
x: {y: string, z?: number};
}
预期行为:
我本以为这不会发出警告,因为 A#x
可以分配给 B#x
。
实际行为:
index.ts(6,3): 错误 TS2564: 属性 'x' 没有初始化器,并且在构造函数中没有被明确分配。
TypeScript版本: 2.7.0-dev.20171226
代码
class A {
x: {y: string} = {y: 'y'};
}
class B extends A {
x: {y: string, z?: number};
}
预期行为:
我本以为这不会发出警告,因为 A#x
可以分配给 B#x
。
实际行为:
index.ts(6,3): 错误 TS2564: 属性 'x' 没有初始化器,并且在构造函数中没有被明确分配。
4条答案
按热度按时间sczxawaw1#
看起来不理想。CC @ahejlsberg。
4si2a6ki2#
注意:这并非TypeScript实现的情况,但在当前阶段-3的类属性中,
x
在B
中是一个完全不同的自有属性,具有相同的名称。这确实意味着,在一个阶段-3兼容的实现中,
(new B).x
将成为一个新自有属性,值为undefined
,因为它缺少一个初始化器。为了在覆盖新属性定义之前复制来自超类构造函数的值,它必须使用= this.x
进行初始化。vybvopom3#
@Kovensky 嗯!阅读一下:https://tc39.github.io/proposal-class-fields/#initialize-public-instance-fields 似乎
[[Fields]]
将有两个条目,第一个是A
的x
,然后是B
的x
,而CreateDataPropertyOrThrow
在评估B
的x
时将分配undefined
。这段代码试图声明现有字段的类型,而不是声明字段本身。这在今天起作用得很好,表达了这个意图。Typescript 甚至会在
B#x
的声明类型不是可分配给A#x
时给出错误:我希望有人能再次检查我的推理,但如果以上都是正确的,那么我认为这个问题可以作为正确工作地关闭。
00jrzges4#
Ryan在#35831上发布了一条非常有用的建议。如果你使用的是至少TS 3.7,那么有一个
declare
修饰符可以用于类属性,让你在子类中缩小属性的类型,而不会发出任何运行时初始化代码,同时它也能让strictPropertyInitialization
满意。