Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 658
Radu Szasz Avatar asked Feb 23 '18 17:02

Radu Szasz


People also ask

How do you access private members of a class in TypeScript?

In TypeScript there are two ways to do this. The first option is to cast the object to any . The problem with this option is that you loose type safety and intellisense autocompletion. The second option is the intentional escape hatch.

How do you implement a class in TypeScript?

Example: Declaring a class The example above declares a constructor for the class. A constructor is a special function of the class that is responsible for initializing the variables of the class. TypeScript defines a constructor using the constructor keyword. A constructor is a function and hence can be parameterized.

How do you write a function inside a class in TypeScript?

Creating a function in TypeScript is similar to the process in JavaScript: You use the function keyword. However, in TypeScript you also have the option to define the type of parameters and return type of the function.

Does TypeScript have private methods?

TypeScript Private MethodsMethods can also be private which is useful for hiding implementation detail of how a Class works to the user of the Class.


1 Answers

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!

like image 97
jcalz Avatar answered Oct 21 '22 18:10

jcalz