TypeScript ``` strictPropertyInitialization with subclasses that refine the types of properties ```

mpgws1up  于 6个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(79)

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' 没有初始化器,并且在构造函数中没有被明确分配。

sczxawaw

sczxawaw1#

看起来不理想。CC @ahejlsberg。

4si2a6ki

4si2a6ki2#

注意:这并非TypeScript实现的情况,但在当前阶段-3的类属性中,xB 中是一个完全不同的自有属性,具有相同的名称。
这确实意味着,在一个阶段-3兼容的实现中,(new B).x 将成为一个新自有属性,值为 undefined,因为它缺少一个初始化器。为了在覆盖新属性定义之前复制来自超类构造函数的值,它必须使用 = this.x 进行初始化。

vybvopom

vybvopom3#

@Kovensky 嗯!阅读一下:https://tc39.github.io/proposal-class-fields/#initialize-public-instance-fields 似乎 [[Fields]] 将有两个条目,第一个是 Ax,然后是 Bx,而 CreateDataPropertyOrThrow 在评估 Bx 时将分配 undefined
这段代码试图声明现有字段的类型,而不是声明字段本身。这在今天起作用得很好,表达了这个意图。Typescript 甚至会在 B#x 的声明类型不是可分配给 A#x 时给出错误:

class A {
  x: {y: string} = {y: 'y'};
}

class B extends A {
}

interface B {
  x: {y: string, z?: number};
}

我希望有人能再次检查我的推理,但如果以上都是正确的,那么我认为这个问题可以作为正确工作地关闭。

00jrzges

00jrzges4#

Ryan在#35831上发布了一条非常有用的建议。如果你使用的是至少TS 3.7,那么有一个declare修饰符可以用于类属性,让你在子类中缩小属性的类型,而不会发出任何运行时初始化代码,同时它也能让strictPropertyInitialization满意。

相关问题