我正在探索在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会像这样工作。
谢谢!
答案 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; } }
MockIdentity
是Identity
的公共兼容版本,但当非模拟副本与模拟副本进行交互时,尝试将其用作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)
在这种情况下,目前的打字稿规范是不可能的。这有一个tracked issue,但它已关闭。
Suggestion: Permit an implementing class to ignore private methods of the implementee class
另见Extending vs. implementing a pure abstract class in TypeScript
答案 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
的公共属性(和方法),然后Pick
将A
缩减为仅其公共属性及其各自的类型。