You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
noImplicitOverride does not complain on abstract methods #44457
You'll need to manually set the tsconfig option in the Playground, as the share link doesn't seem to contain that option.
💻 Code
abstractclassHello{abstractdoesNotComplain(): void;}classWorldextendsHello{// should complain here for missing override keyworddoesNotComplain(){}}
🙁 Actual behavior
With noImplicitOverride=true, tsc is fine with the above snippet
🙂 Expected behavior
With noImplicitOverride=true, it should complain about the missing override keyword.
Reasoning
I can add an override keyword for implementations of abstract methods. So if I can define it as override, there must be an implicit override if I don't write it manually and the option noImplicitOverride should catch that.
Why do I want this to happen aside from the confusing/incorrect wording of the option?
If I use the override keyword manually, I get an error if the base class removes the abstract method declaration and I can properly update my code. If I didn't have the override keyword, I would have dead code, which needs to be handled differently in newer versions of the base class (for example by registering an event listener instead of implementing an abstract method).
Wenlu Wang (@Kingwl) Thanks for the info. Looking at the PR description, it was at least not very clear and the comment you highlighted seems more about semantics than about usefulness. I would expect noImplicitOverride to help me find possible errors.
I guess if this is not wanted in noImplicitOverride, It might be possible to create an eslint rule to add that extra safety.
(Crossposting this comment) This is intentional. The mental model to have in place here is, "If I typo this method name, what will happen?"
If you typo the name of an abstract member (assuming you're in a concrete class), you'll get an error, because you failed to implement all abstract members. override isn't necessary to prevent you from making this mistake, so you don't need to write override in this case.
If you typo the name of an optional member, you'll now have calculateHeight and cacluateHeight, and the latter will just go silently uncalled forever. override is necessary to prevent you from making this mistake, so when overriding an optional member, you should be writing override.
Write a new class, implement abstract method, make a typo
Wanting to get informed about typo.
While I would say, that this is a perfectly valid scenario, I would say the more important scenario is:
Write new class, implement abstract method, test => all good
Update dependency, abstract method has been renamed or removed
Wanting to get informed about this change.
When implementing an abstract method for the first time, you usually make sure it works correctly, so you're less likely to make a mistake here. But if you update a dependency and the abstract method has been removed from the base class (not just renamed), you will at best be left with dead code, at worst with a broken feature.
Reacted by Vitaliy Ryaboy, Paul Gschwendtner, Filatov Dmitry, Aylon Carrijo, max-sistemich-kisters and Jesper Engberg
It can also be argued that you should only be able to write override foo() in places where super.foo() is legal to write, and that doesn't apply for abstract members.
People will have varying expectations and at the end of the day we have to pick one for clarity and folks who had different expectations will have to adjust a bit.
That is true, though at least Java uses @Override for interfaces as well.
So we either need to introduce a new keyword "implement" (not fixed on the naming), which can be used for methods, which implement abstract methods or optional properties, or we should handle both cases in exactly the same way under one keyword "override". I'd be fine with implement foo() {} for all places, where super.foo() is not legal.
Reacted by Ewout van der Linden, Vitaliy Ryaboy, Aylon Carrijo and max-sistemich-kisters
Activity
MartinJohns commentedon Jun 6, 2021
Related: #44439
Kingwl commentedon Jun 6, 2021
It's working as expected.
You can see this thread to learn more.
Lusito commentedon Jun 6, 2021
Martin Johns (@MartinJohns) that's a different issue and has nothing to do with this one.
Wenlu Wang (@Kingwl) Thanks for the info. Looking at the PR description, it was at least not very clear and the comment you highlighted seems more about semantics than about usefulness. I would expect noImplicitOverride to help me find possible errors.
I guess if this is not wanted in noImplicitOverride, It might be possible to create an eslint rule to add that extra safety.
RyanCavanaugh commentedon Jun 7, 2021
(Crossposting this comment) This is intentional. The mental model to have in place here is, "If I typo this method name, what will happen?"
If you typo the name of an abstract member (assuming you're in a concrete class), you'll get an error, because you failed to implement all abstract members.
overrideisn't necessary to prevent you from making this mistake, so you don't need to writeoverridein this case.If you typo the name of an optional member, you'll now have
calculateHeightandcacluateHeight, and the latter will just go silently uncalled forever.overrideis necessary to prevent you from making this mistake, so when overriding an optional member, you should be writingoverride.Lusito commentedon Jun 7, 2021
Ryan Cavanaugh (@RyanCavanaugh)
So your scenario is:
While I would say, that this is a perfectly valid scenario, I would say the more important scenario is:
When implementing an abstract method for the first time, you usually make sure it works correctly, so you're less likely to make a mistake here. But if you update a dependency and the abstract method has been removed from the base class (not just renamed), you will at best be left with dead code, at worst with a broken feature.
RyanCavanaugh commentedon Jun 7, 2021
I don't disagree.
It can also be argued that you should only be able to write
override foo()in places wheresuper.foo()is legal to write, and that doesn't apply forabstractmembers.People will have varying expectations and at the end of the day we have to pick one for clarity and folks who had different expectations will have to adjust a bit.
Lusito commentedon Jun 7, 2021
That is true, though at least Java uses
@Overridefor interfaces as well.So we either need to introduce a new keyword "implement" (not fixed on the naming), which can be used for methods, which implement abstract methods or optional properties, or we should handle both cases in exactly the same way under one keyword "override". I'd be fine with
implement foo() {}for all places, wheresuper.foo()is not legal.typescript-bot commentedon Jun 10, 2021
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…
feat(dev-infra): add lint rule to enforce no-implicit-override abstra…