打字稿类实现与私有函数类

问题描述 投票:5回答:4

我正在研究实施有在打字稿一类一类的可能性。

因此,我写了下面的代码Playground link

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

class B implements A {
    public g() { console.log("g"); }
}

而我得到的错误:Class 'B' incorrectly implements class 'A' --- property 'f' is missing in type 'B'再加上我其实是extends的建议。

于是,我就做一个私有字段名为f(因为它检测到他们有不同的访问修饰符public没有工作)Playground link

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

  • 为什么私有成员即使事情 - 如果我实现使用不同的数据结构相同的算法,我必须声明一个名为同一只进行类型检查的缘故的东西吗?
  • 为什么作为一个私有函数实现f当我得到这个错误吗?

我不会在实践中做到这一点,但我很好奇,为什么TS是这样工作的。

谢谢!

typescript implements
4个回答
9
投票

这个问题Microsoft/TypeScript#18499讨论为什么在确定兼容性时,需要私有成员。通过@RyanCavanaugh一个remark是特别相关的和照明:

Allowing the private fields to be missing would be an enormous problem, not some trivial soundness issue. Consider this code:

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 is a public-compatible version of Identity but attempting to use it as one will crash in sameAs when a non-mocked copy interacts with a mocked copy.

只要是明确的,这里的地方,它会失败:

const identity = new Identity();
const mockIdentity = new MockIdentity();
identity.sameAs(mockIdentity); // boom!

因此,有充分的理由,为什么你不能做到这一点。


作为一种变通方法,您可以拉出只是一个映射类型像这样一类的公共属性:

type PublicPart<T> = {[K in keyof T]: T[K]}

然后你就可以有B工具不APublicPart<A>

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

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

希望帮助;祝好运!



1
投票

这是从根本上由于私有成员的可见性的作用域的类型,而不是实例。这意味着该类型T的所有对象的访问类型T的其他对象的士兵

这不是nominatively类型语言问题为T的所有实例继承了T的执行,但由于打字稿的结构类型,这意味着我们不能想当然地认为是满足T总实例都声明类型T的类的实现。

这意味着,私有作用域成员必须是该类型的公共合同的一部分,否则该结构类型T的对象可以调用具有相同结构类型另一个对象的非现有的专用构件。

被迫有士兵是一个公共类型的合同的一部分是坏的,本来是可以避免的范围界定士兵的实例,而不是类型。


0
投票

从打字稿外的现成支持目前的解决方案是简单地

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

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

说明:keyof A只返回A的公共属性(和方法),并Pick会再向下微调A只有它的公共属性和它们各自的类型。

© www.soinside.com 2019 - 2024. All rights reserved.