TypeScript类实现具有私有函数的类

Rad*_*asz 5 implements typescript

我正在探索在TypeScript中实现类的可能性.

因此,我编写了以下代码Playground链接:

class A {
    private f() { console.log("f"); }
    public g() { console.log("G"); }
}

class B implements A {
    public g() { console.log("g"); }
}
Run Code Online (Sandbox Code Playgroud)

我得到了错误:Class 'B' incorrectly implements class 'A' --- property 'f' is missing in type 'B'加上我实际意味着的建议extends.

所以我试着创建一个私有字段f(public没有工作,因为它检测到它们有不同的访问修饰符)Playground链接

现在我得到了错误:Class 'B' incorrectly implements class 'A'. Types have separate declarations of a private property 'f'; 这让我很困惑:

  • 为什么私有成员甚至很重要 - 如果我使用不同的数据结构实现相同的算法,我是否必须为了类型检查而声明一些名称相同的东西?
  • 为什么在实现f私有函数时会出现错误?

我不会在实践中这样做,但我很好奇TS为何如此工作.

谢谢!

jca*_*alz 11

问题Microsoft/TypeScript#18499讨论了在确定兼容性时需要私有成员的原因.一个此言通过@RyanCavanaugh是特别重要和富有启发性:

允许私有字段丢失将是一个巨大的问题,而不是一些微不足道的健全问题.请考虑以下代码:

class Identity { private id: string = "secret agent"; public sameAs(other: Identity) { return this.id.toLowerCase() === other.id.toLowerCase(); } } class MockIdentity implements Identity { public sameAs(other: Identity) { return false; } }
MockIdentity是公共兼容版本Identity但尝试使用它,因为sameAs当非模拟副本与模拟副本交互时会崩溃.

需要明确的是,这是失败的地方:

const identity = new Identity();
const mockIdentity = new MockIdentity();
identity.sameAs(mockIdentity); // boom!
Run Code Online (Sandbox Code Playgroud)

所以,有充分的理由说明你不能这样做.


作为一种解决方法,您可以使用如下映射类型来提取类的公共属性:

type PublicPart<T> = {[K in keyof T]: T[K]}
Run Code Online (Sandbox Code Playgroud)

然后你可以B实现A但不是PublicPart<A>:

class A {
    private f() { console.log("f"); }
    public g() { console.log("G"); }
}

// works    
class B implements PublicPart<A> {
    public g() { console.log("g"); }
}
Run Code Online (Sandbox Code Playgroud)

希望有所帮助; 祝好运!

  • “具有私有属性的类的实例可以访问同一类的其他实例上的该属性”——有趣的是,我不知道这一点。谢谢 (2认同)

Eud*_*des 6

当前具有 Typescript 开箱即用支持的解决方案很简单

class A {
    private f() { console.log("f"); }
    public g() { console.log("G"); }
}

class B implements Pick<A, keyof A> {
    public g() { console.log("g"); }
}
Run Code Online (Sandbox Code Playgroud)

说明:keyof A仅返回 的公共属性(和方法)A,然后Pick将修剪A为仅其公共属性及其各自的类型。