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

时间:2018-02-23 17:50:18

标签: typescript implements

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

因此,我编写了以下代码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会像这样工作。

谢谢!

4 个答案:

答案 0 :(得分:9)

问题Microsoft/TypeScript#18499讨论了在确定兼容性时需要私有成员的原因。 @RyanCavanaugh的一个remark特别相关且具有启发性:

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

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; } }
MockIdentityIdentity的公共兼容版本,但当非模拟副本与模拟副本进行交互时,尝试将其用作sameAs版本会在const identity = new Identity(); const mockIdentity = new MockIdentity(); identity.sameAs(mockIdentity); // boom! 中崩溃。

只是要清楚,这里会失败:

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

所以,有很好的理由说明你无法做到这一点。

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

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"); } }

{{1}}

希望有所帮助;祝你好运!

答案 1 :(得分:2)

答案 2 :(得分:1)

这基本上是由于私有成员的可见性范围限定为类型,而不是实例。这意味着T类型的所有对象都可以访问T类型的其他对象的私有。

这在主格类型语言中不是问题,因为T的所有实例都继承了T的实现,但由于typescript是结构类型的,这意味着我们不能假设所有满足T的实例都具有类的实现。声明类型T。

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

被迫让私有部门成为公共类型合同的一部分是不好的,并且可以通过确定实例的私有部分而不是类型来避免。

答案 3 :(得分:0)

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"); }
}

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