Estus Flask
Estus Flask

Reputation: 222344

Private property in class implementation

There is an interface implementation:

interface ISome {
    some: Function;
}

class Awesome implements ISome {
    constructor(private some: Function) {}
}

This triggers an error:

Awesome incorrectly implements interface ISome . Property 'some' is private in type 'Awesome' but not in type 'ISome'.

But adding private to ISome is not possible,

private some: Function;

triggers

property or signature expected

How this should be treated?

Upvotes: 1

Views: 2141

Answers (2)

Venryx
Venryx

Reputation: 17989

If you only need to make a given method "un-overridable" by extension classes, you can add some assert code to the class's constructor which verifies that the methods have not been modified for the new instance.

It's not ideal (eg. it's run-time rather than compile-time), but it's the next best thing that I'm aware of.

Example:

function HasSealedProps(target: Object) {
    let oldConstructor = target.constructor;
    target.constructor = function() {
        for (let key in target["prototype"]) {
            let method = target["prototype"][key];
            if (method.sealed) {
                console.assert(this[key] == method, `Cannot override sealed method "${key}".`);
            }
        }
        return oldConstructor.apply(this, arguments);
    };
}
function Sealed(target: Object, key: string) {
    target[key].sealed = true;
}

interface MyInterface {
    DoNotOverrideMe: Function;
}
@HasSealedProps
class MyClass implements MyInterface {
    @Sealed DoNotOverrideMe() {
        console.log("I shall always exist. No one shall take my place.");
    }
}

Upvotes: 0

artem
artem

Reputation: 51589

How this should be treated?

I'd say by questioning intent and/or some of the assumptions.

Awesome incorrectly implements interface ISome . Property 'some' is private in type 'Awesome' but not in type 'ISome'.

Private properties can not serve as implementation for the interface. Private means it's not accessible outside of the class, so if you have

class Awesome {
    private some: Function
}

you can't pass instance of that class to

function doSomething(awesome: {some: Function}) { ... }

because there is no way it can get some which is private in Awesome.

Looking from another side, if you want some to be private, what's the point of exposing it in the interface? Private property is not accessible outside the type that declared it, but there is nothing in the interface that could have access to it - interface is a contract, it contains no implementation.

What is the intent of the interface? To make sure that particular class has particular private property? But how is just having private implementation in the class not sufficient?

Or, was the purpose to have some public property, backed by private implementation? Then this would suffice:

interface ISome {
    some: Function;
}

class Awesome implements ISome {
    public some: Function;

    constructor(private someImpl: Function) {
        this.some = someImpl
    }


}

Upvotes: 1

Related Questions