Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
933 views
in Technique[技术] by (71.8m points)

TypeScript class implements class with private functions

I was exploring the possibility of having a class implementing a class in TypeScript.

Hence, I wrote the following code Playground link:

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

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

And I got the error: Class 'B' incorrectly implements class 'A' --- property 'f' is missing in type 'B' coupled with a suggestion that I actually meant extends.

So I tried to make a private field called f (public didn't work as it detects they have different access modifiers) Playground link

Now I get the error: Class 'B' incorrectly implements class 'A'. Types have separate declarations of a private property 'f'; this leaves me very confused:

  • why do private members even matter - if I implement the same algorithm using different data structures, will I have to declare something named the same just for the sake of type checking?
  • why do I get the error when implementing f as a private function?

I wouldn't do this in practice, but I am curious about why TS works like this.

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The issue Microsoft/TypeScript#18499 discusses why private members are required when determining compatibility. The reason is: class private members are visible to other instances of the same class.

One remark by @RyanCavanaugh is particularly relevant and illuminating:

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.

Just to be clear, here's where it would fail:

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

So, there are good reasons why you can't do it.


As a workaround, you can pull out just the public properties of a class with a mapped type like this:

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

And then you can have B implement not A but 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"); }
}

Hope that helps; good luck!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...