TypeScript class implements class with private functions

The current solution with out-of-the-box support from Typescript is simply

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

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

Explanation: keyof A only returns public properties (and methods) of A, and Pick will then down trim A to only its public properties and their respective type.


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!