How can i avoid a function to be overridden in the Child Class in TypeScript ?
Update for TS 4.3 and above
Typescript 4.3 adds a new compiler option called noImplicitOverride
in this PR. This makes it an error to mistakenly override class methods without the override
keyword
class Base{
method() {}
method2 () {}
}
class Derived extends Base {
method() {} // err
override method2() {} // ok
}
(playground does not support the option yet, but works in vs code)
Original answer pre 4.3
There is no way to prevent a public/protected member from beeing overriden. The compiler will trigger an error if you to this with private members only. A feature for this has been proposed but not implemented
In Javascript the short answer is, "yes, we can". I have no experience with Typescript but I understand it is a superset of Javascript so I guess that means if you can do it in Javascript then you can do it in Typescript - please correct me if I am wrong.
Running in nodejs
in interactive console mode:
class A {
constructor(){
Reflect.defineProperty(this, 'protectedFn', {
value: ()=>{ return "hello" },
configurable: false,
writable: false,
enumerable: true
})
}
}
class B extends A {
constructor(){
super()
this.protectedFn=()=>{}
}
}
class C extends A {
constructor(){
super()
Reflect.defineProperty(this, 'protectedFn', {
value: (v)=>{ return "goodbye" }
})
}
}
class D extends A {
constructor(){
super()
Reflect.deleteProperty(this, 'protectedFn')
}
}
let a = new A();
let b = new B();
let c = new C();
let d = new D();
a.protectedFn()
c.protectedFn()
d.protectedFn()
results in
> let a = new A();
> let b = new B();
Thrown:
TypeError: Cannot assign to read only property 'protectedFn' of object '#<B>'
at new B (repl:4:19)
> let c = new C();
> let d = new D();
> a.protectedFn()
'hello'
> c.protectedFn()
'hello'
> d.protectedFn()
'hello'
We see the constructor of B
invoked a throw
using the simple assignment form.
The constructor of C
didn't throw, but it silently failed. Ouch. The return result of Replace.defineProperty
is actually false and should be checked.
Same with D
.
Interestingly, using ES5 Object.*
instead ES6 Replace.*
results in a throw
upon failure. Also Object.deleteProperty
does not exist.