TypeScript: Can not declare protected methods without implementation in TS 2.0
Sometimes I use mixins to share some protected logic between several classes:
class Mixin {
protected doSomething(): void {
}
}
class Base {
}
class Sample extends Base {
run() {
this.doSomething();
}
protected doSomething(): void; // error TS2391: Function implementation is missing or not immediately following the declaration.
}
// uncomment the following code to fix the complilation in v1.8 and earlier
//namespace Sample {
//}
// extend Sample.prototype from Mixin.prototype
The code above raises the error TS2391. But uncommenting namespace Sample after the class definition changed behavior: the compilation became successful before version 2.0. Maybe it was a bug or undocumented feature, I don’t know. But it worked and I used it since early versions (about 1.3 or 1.4), including 1.8.10. This behavior changed in 2.0, now introducing the namespace don’t fix compilation:(
I can declare mixining method as a property:
class Sample extends Base {
protected doSomething: () => void;
}
But in this case I can’t override this method later:
class Child extends Sample {
protected doSomething(): void { // error TS2425: Class 'Sample' defines instance member property 'doSomething', but extended class 'Child' defines it as instance member function.
super.doSomething(); // error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword.
}
}
Also this way is inconvenient and confusing.
If method doSomething would be public, I can declare it in interface Sample and TypeScript merge it with the class. But this trick does not work with protected methods.
I tried to mark the method as optional (although it is mandatory in fact):
protected doSomething?(): void;
But now compilation with --strictNullChecks throws an error error TS2532: Object is possibly 'undefined'.
The only workaround that I found is to add a fake implementation to the method:
protected doSomething(): void { }
But this generates redundant JavaScript and misleads code reviewers. Unacceptable:( So this is real blocker for me to update to version 2.0.
Adding a namespace with the same name was not clean of course. The solution would be to allow using declare inside a class body:
class Sample extends Base {
run() {
this.doSomething();
}
declare protected doSomething(): void;
}
I suppose it is not so difficult to implement this.
P.S. Sorry for my English:(
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 17 (6 by maintainers)
in cases of conflicting declarations, you will have to redefine them in the interface. doing so changing the visibility to
publicthough. do not think there is a way around this.yes, the interface inherits all the members from the class.
protectedandprivatemembers can only be declared in a class though. so this is the only way an interface can get aprotectedor aprivatemember.