Repository navigation
Support override keyword on class methods #2000
Description
(Update by @RyanCavanuagh)
Please see this comment before asking for "any updates", "please add this now", etc.. Comments not meaningfully adding to the discussion will be removed to keep the thread length somewhat reasonable.
(NOTE, this is not a duplicate of Issue #1524. The proposal here is more along the lines of the C++ override specifier, which makes much more sense for typescript)
An override keyword would be immensely useful in typescript. It would be an optional keyword on any method that overrides a super class method, and similar to the override specifier in C++ would indicate an intent that "the name+signature of this method should always match the name+signature of a super class method". This catches a whole range of issues in larger code bases that can otherwise be easily missed.
Again similar to C++, it is not an error to omit the override keyword from an overridden method. In this case the compiler just acts exactly as it currently does, and skips the extra compile time checks associated with the override keyword. This allows for the more complex untyped javascript scenarios where the derived class override does not exactly match the signature of the base class.
Example use
class Animal {
move(meters:number):void {
}
}
class Snake extends Animal {
override move(meters:number):void {
}
}Example compile error conditions
// Add an additional param to move, unaware that the intent was
// to override a specific signature in the base class
class Snake extends Animal {
override move(meters:number, height:number):void {
}
}
// COMPILE ERROR: Snake super does not define move(meters:number,height:number):void
// Rename the function in the base class, unaware that a derived class
// existed that was overriding the same method and hence it needs renaming as well
class Animal {
megamove(meters:number):void {
}
}
// COMPILE ERROR: Snake super does not define move(meters:number):void
// Require the function to now return a bool, unaware that a derived class
// existed that was still using void, and hence it needs updating
class Animal {
move(meters:number):bool {
}
}
// COMPILE ERROR: Snake super does not define move(meters:number):voidIntelliSense
As well as additional compile time validation, the override keyword provides a mechanism for typescript intellisense to easily display and select available super methods, where the intent is to specifically override one of them in a derived class. Currently this is very clunky and involves browsing through the super class chain, finding the method you want to override, and then copy pasting it in to the derived class to guarantee the signatures match.
Proposed IntelliSense mechanism
Within a class declaration:
- type override
- An auto complete drop down appears of all super methods for the class
- A method is selected in the drop down
- The signature for the method is emitted into the class declaration after the override keyword.
Activity
stephanedr commentedon Feb 10, 2015
Indeed a good proposal.
However what about the following examples, which are valid overrides to me:
Additionally I would add a compiler flag to force the override keyword to be present (or reported as a warning).
The reason is to catch when renaming a method in a base class that inherited classes already implement (but not supposed to be an override).
rwyborn commentedon Feb 10, 2015
Ah nice examples. Generally speaking I would expect the use of the override keyword to enforce exact matching of signatures, as the goal of using it is to maintain a strict typed class hierarchy. So to address your examples:
So example (2.) is actually a great demo of how an override keyword can catch subtle edge cases at compile time that would otherwise be missed! :)
And I would again stress that both examples may be valid in specific controlled/advanced javascript scenarios that may be required... in this case users can just choose to omit the override keyword.
NoelAbrahams commentedon Feb 11, 2015
This will be useful. We currently work around this by including a dummy reference to the super method:
But this only guards against the second case: super methods being renamed. Changes in signature do not trigger a compilation error. Furthermore, this is clearly a hack.
I also don't think that default and optional parameters in the derived class method's signature should trigger a compilation error. That may be correct but goes against the inherent flexibility of JavaScript.
stephanedr commentedon Feb 11, 2015
Rowan Wyborn (@rwyborn)
It seems we don't expect the same behaviour.
You would use this override keyword to ensure a same signature, whereas I would use it more as a readibiliy option (so my request to add a compiler option to force its usage).
In fact what I would really expect is that TS detects invalid overriding methods (even without the use of override).
Typically:
should raise an error, because it's really an override of Animal.move() (JS behaviour), but an incompatible one (because height is not supposed to be optional, whereas it will be undefined if called from an Animal "reference").
In fact using override would only confirm (by the compiler) that this method really exists in the base class (and so with a compliant signature, but due to the previous point, not due to the override keyword).
rwyborn commentedon Feb 11, 2015
stephanedr , speaking as a single user I actually agree with you that the compiler should just always confirm the signature, as I personally like to enforce strict typing within my class hierarchies (even if javascript doesn't!!).
However in proposing that this behavior is optional via the override keyword I am trying to keep in mind that ultimately javascript is untyped, and hence enforcing the strict signature matching by default would result in some javascript design patterns no longer being expressible in Typescript.
kungfusheep commentedon Mar 14, 2015
Rowan Wyborn (@rwyborn) I'm glad you mentioned the C++ implementation because that's exactly how I imagined it should work before I got here - optionally. Although, a compiler flag that forced the use of the override keyword would go down well in my book.
The keyword would allow compile time errors for a developers clumsy typing, which is what worries me most about overrides in their current form.
Currently (as of 1.4) the
Implementationclass above would just declare a new method and the developer would be none the wiser until they notice their code isn't working.RyanCavanaugh commentedon May 4, 2015
Discussed at suggestion review.
We definitely understand the use cases here. The problem is that adding it at this stage in the language adds more confusion than it removes. A class with 5 methods, of which 3 are marked
override, wouldn't imply that the other 2 aren't overrides. To justify its existence, the modifier would really need to divide the world more cleanly than that.hdachev commentedon May 5, 2015
Please excuse the whining, but honestly, while your argument does apply to the
publickeyword in a language where everything is public by default, quite world dividing indeed, having things likeabstractand an optionaloverridekeyword will simply help developers feel safer, make less mistakes and waste less time.Overriding is one of the few remaining highly-typo-sensitive aspects of the language, because a mistyped overriding method name is not an obvious compile time problem. The benefit of
overrideis obvious, as it you allows you to state your intention to override - if the base method doesn't exist its a compile time error. All hail the type system. Why would anyone not want this?rwyborn commentedon May 5, 2015
I concur 100% with Hristo Dachev (@hdachev) , the small inconsistency referred too by Ryan Cavanaugh (@RyanCavanaugh) is easily out weighed by the benefits of the keyword in bringing compile time checks to method overrides. I would again point out that C++ uses an optional override keyword successfully in exactly the same way as suggested for typescript.
I can not emphasize enough how much of a difference override checking makes in a large scale code base with complex OO trees.
Finally I would add that if the inconsistency of an optional keyword really is a concern, then the C# approach could be used, that is the mandatory use of either the "new" or "override" keywords:
RyanCavanaugh commentedon May 5, 2015
This isn't analogous to
publicbecause a property without an access modifier is known to be public; a method withoutoverrideis not known to be non-override.Here's a runtime-checked solution using decorators (coming in TS1.5) that produces good error messages with very little overhead:
Running this code produces an error:
Since this code runs at class initialization time, you don't even need unit tests specific to the methods in question; the error will happen as soon as your code loads. You can also sub in a "fast" version of
overridethat doesn't do any checking for production deployments.217 remaining items
aipirvu commentedon Jan 18, 2021
Because with a final you prevent the use of that method in the extended class as with override that is permitted but you need to explicitly mention your intent and the writer of the super/base method will know that whoever overrides it will make a conscious choice to call the super method or not.
As for the familiarity of javascript developer with
override, that is not necessarily a valid argument. So is the case with other features that TypeScript has over JavaScript and that is the exact reason why it is used. The functionality can however be an option "explcitOverride" that is turned off by defaultaprilmintacpineda commentedon Jan 19, 2021
What's the latest update? seems like it's still unclear and it's been almost 6 years...
Kingwl commentedon Jan 19, 2021
Actually there's a PR: #39669
felixhirt commentedon Jan 20, 2021
seems its also still planned to be included in the next release: #41601 (at least at the time of writing this)
DanielRosenwasser commentedon Mar 26, 2021
Thank you Wenlu Wang (@Kingwl), and thank you Paul Cody (@pcj) for the groundwork in the initial proof-of-concept!
seiyria commentedon Apr 5, 2021
I'm not sure where to ask this, but it seems like
tscis compiling and leaving theoverridekeyword in the compiled result. Is this something other folks are seeing? It seems like it needs the signature to match exactly, or it will show up in the output, see here:https://www.typescriptlang.org/play?ts=4.3.0-beta#code/LAKAxgNghgzjAEBlADgUwheBvUp72QFcAjCASzHgHNUAXAYQAsoAnGmACgEoAueAO0IBbYqhbY8+eCzqEW-eAAYA3JIC+uEPiKkK1OgBE5UWmQD2-bn0EixErVJm05Cles3aS5SmFi0r8ABuZmQAJtgaIJGgkLAIABJmEACeAILG8KgAHrSo-KEIKOiYOCCSZoFiLGGo+gzMbKicXPZS0rLy8ACMbg7RDhVVNXVGLCbmlrwCwqLipW1OLvAAzL34-fiDLNWhtb4w-lPBYa3w-WpAA
abdulkareemnalband commentedon Apr 5, 2021
Also
.d.tsfile is missingoverride.Is it by design? aka for back compat with old ts compilers
jakebailey commentedon Apr 5, 2021
I don't see a reason why
.d.tsfiles would need to contain that keyword; the override check is only useful for each individual class (as it's saying "this class you are writing has methods that don't declare they are overrides"). You can't really do anything with the knowledge that some other class has overriden a method from one of its own parent classes.Leaving "override" in the JS source definitely sounds like a bug though. 🙂
DanielRosenwasser commentedon Apr 5, 2021
Jake is right. I've opened #43535 to track the JS output bug.
legistek commentedon Sep 9, 2021
This is a fantastic feature but what about taking it a step farther and requiring use of the
virtualkeyword on the base class so you can actually control when you want to allow sub-classes to override or not? That could also be an opt-in switch,noImplicitVirtual.There are often situations where overriding a function without calling
supercould break the application.