如何使用派生类中自己的属性正确重写基类原型中的访问器(getter)?错误 TS2610

Dan*_*iel 5 typescript

我有这个有效的 JavaScript 代码:

class Base {
    // Base has an accesor in the prototype
    get foo() {
        return "getter Base";
    }
}

class Deriv extends Base {
    // I want define here an own property, hiding the access to the getter,
    // but in TypeScript...
    
    // ERROR: 'foo' is defined as an accessor in class 'Base', but is
    // overridden here in 'Deriv' as an instance property. (2610)
    foo = "prop Deriv";
}
Run Code Online (Sandbox Code Playgroud)

使用useDefineForClassFields: true

我正在尝试做什么

基本上,我希望基类在原型中具有 getter,然后能够在派生类中定义自己的属性(可枚举)。我认为这样做有非常充分的理由,例如在基类中拥有默认算法(或公开某些私有状态等),但将其替换为派生类实例中定义的属性。

TypeScript 失败并出现错误 TS2610,如代码片段所示。我记得看到拉取请求导致这种情况发生错误,我现在不记得数字(认为是#37894)。我知道这段代码正在使用[[Define]]语义,因此如果我在基类中有该属性的设置器,则不会调用它。但这正是我想要的!,然而 TS 抱怨道。

我尝试过的

声明与接口合并,但错误仍然存​​在:

class Base {
    get foo() { return "getter Base"; }
}

interface Deriv {
    readonly foo: string; // Same error here...
}
class Deriv extends Base {}
Run Code Online (Sandbox Code Playgroud)

通过在构造函数中定义属性Object.defineProperty。当然,它是有效的,因为 TS 不检查这一点,但现在类型是撒谎的,因为派生类从基类型“继承”了 getter 声明。例如,oin的推断类型const o = { ...new Deriv() }不包括,foo因为它是原型中的 getter。

// @ts-ignore。当然它有效,但我认为没有理由对此进行更多评论......

declare readonly foo: string在派生类中使用。我以为这行不通,但值得一试。遇到同样的错误。

问题/最终意见

有一个更好的方法吗?

[[Set]]如果我没记错最初的 PR,其背后的基本原理是为了防止语义变化带来的意外[[Define]]。问题是我找不到一个好的方法来选择这种行为并进行良好的打字。

相关链接:

PR:属性覆盖访问器总是出错

问题:提案:也允许环境属性声明覆盖访问器