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
I was thinking it could be useful to have a way to specify that a class should not be subclassed, so that the compiler would warn the user on compilation if it sees another class extending the original one.
On Java a class marked with final cannot be extended, so with the same keyword on TypeScript it would look like this:
finalclassfoo{constructor(){}}classbarextendsfoo{// Error: foo is final and cannot be extendedconstructor(){super();}}
a class with private constructor is not extendable. consider using this instead.
Reacted by Stefano Baghino, Stephen Rayner, Jan Molak, AnyhowStep, Juan Pablo de la Torre, Jacob Schneider, Stijn Rogiest, Diego A. Zapata Häntsch, Nagesh Singh and Ilia Andrienko
Reacted by Ilia Shkuratov, Juande Martos, Giancarlo Dalle Mole, Daniel M., David Paz, Tommaso Ricci, Carlo Palinckx, Julien Pinto, levp, Louis-Dominique Dubeau and 187 more
Doesn't private constructor also make a class not instantiatable out of the class? It's not a right answer to final class.
Reacted by Elephant-Vessel, Michael K, Ankit Gupta, Gregory, Raphael Ferreira, ebaersoft, Juande Martos, SlickNutter, Daniel M., Tommaso Ricci and 105 more
Java and/or C# uses the final class to optimize your class at runtime, knowing that it is not going to be specialized. this i would argue is the main value for final support. In TypeScript there is nothing we can offer to make your code run any better than it did without final.
Consider using comments to inform your users of the correct use of the class, and/or not exposing the classes you intend to be final, and expose their interfaces instead.
Reacted by Jan Molak, Sergey S. Volkov, Chris Williams and José Lastra
Reacted by Kayleigh, Chris Smith, Tomáš Hübelbauer, Huan Li, avin-shum, Raman Fedaseyeu, enekesabel, Victor Jonsson, John Plaisted, Nathan Phillip Brink and 197 more
Reacted by Artur Klesun, LCLP, Yechan Choi, i3ym, Shane , Grigorii Sokolik, Paul Shryock, a11delavar, neeko-cat and snarbles2
I do not agree with that, instead I agree with duanyao. Private does not solve that issue, because I also want classes which are final to be instanciateable using a constructor. Also not exposing them to the user would force me to write additional factories for them. For me the main value of final support is, that it prevents users from making mistakes.
Arguing like that: What does TypeScript offer to make my code run faster, when I use types in function signatures? Isn't it also only for preventing users from making mistakes? I could write comments describing which types of values a user should pass in as a parameter. It's a pitty, that such extensions like a final keyword are just pushed away, because on my opinion it collides with the original intension of typescript: make JavaScript safer by adding a compilation level, which performs as many checks as possible to avoid as many mistakes upfront as possible. Or did I misunderstand the intention of TypeScript?
Reacted by Lazar Ljubenović, ebaersoft, Yaojian, Benjamin Hough, igolopolosov, SlickNutter, Chris Miemiec, Leandro-Albano, Sławek, levp and 157 more
There should also be a final modifier for methods:
class Foo {
final fooIt():void{
}
}
class Bar {
fooIt():void {
}
}
// => Method fooIt of Bar cannot override fooIt of Foo, because it is final.
E.g. I often use following pattern, where I want to urgently avoid fooIt to be overridden:
import Whatever ...
abstract class Foo {
private ImportantVariable:boolean;
protected abstract fooIt_inner:Whatever();
public final fooIt():Whatever() {
//do somestate change to aprivate member here, which is very crucial for the functionality of every Foo:
ImportantVariable = true;
//call the abstract inner functionality:
return this.fooIt_inner();
}
}
Reacted by Gregory, Raphael Ferreira, Jorge Fuentes, Braden Snell, Pramod Chandoria, Francisco de Gouveia, Nick Fisher, Patrick Desjardins, bykbtzr, Atli Þór Jónsson and 122 more
Reacted by Dimitar Dimitrov, Kirill Agalakov, Akio, Edoardo Luppi, Lorenzo Bugiani, Jan Šeda, misabiko, Dariusz Filipiak, Lianghai-Yang, Onome Agwa and 16 more
The argument about cost vs. utility is a fairly subjective one. The main concern is every new feature, construct, or keyword adds complexity to the language and the compiler/tools implementation. What we try to do in the language design meetings is to understand the trade offs, and only add new features when the added value out weights the complexity introduced.
The issue is not locked to allow members of the community to continue adding feedback. With enough feedback and compelling use cases, issues can be reopened.
Reacted by Lacho Tomov
Reacted by theta3, Renato Cara, Rafael Pinho, Romain THD, Thomas Eding, a11delavar, Tomas Rimkus, Akash Kava, Derekmod, smaspe and 9 more
Reacted by Kirill Bulgakov, Brian Kim, Han Seoul-Oh and TenviLi
Reacted by igolopolosov, Klaus Reimer, Ahmed Medhat Tawfiq, Rémi Lelaidier - RLFly.fr, Thomas Hudson, Daniel Shuy, Engin Semih Basmacı, theta3, Siddharth VP, Gabriele Tomberli and 6 more
Actually final is very simple concept, does not add any complexity to the language and it should be added. At least for methods. It adds value, when a lot of people work on a big project, it is valuable not to allow someone to override methods, that shouldn't be overridden.
Reacted by Juande Martos, igolopolosov, Dorian Smiley, BehindTheMath, Alex Rothuis, Giorgi Beridze, Kirill Agalakov, Thomas Jensen, Tomáš Hübelbauer, harshudhwani and 97 more
Well, that's what the quotes mean! Although, it's certainly more advanced than var.
Either way, that's all you got from the post? 🤦♂️ that's not the point, it is that "most users" won't make use of this and that's the "reasonable" expectation before implementing a feature.
Also, just showing a hack that can achieve the desired compilation error in the meantime. Which I'll be deleting since you're just a bunch of ungrateful ones.
Miguel Leon (@miguel-leon), I'm sorry if I made you feel like your comment wasn't welcome. Your opinion is just as valid as mine.
I was disagreeing with part of what you said, and explaining why I disagreed. Disagreeing isn't a bad thing, is it? I like hearing opinions which are different than mine; that's how we all learn.
"most users" won't make use of this
How do you or I know what most users will do? 🤷
I realize OOP isn't trendy on social media right now, and I probably won't find popular YouTubers writing final classes in their videos. But Object-Oriented Programming is a fundamental concept in Computer Science. It's been around since the 1950's, prominently-used since the 1970's and 1980's, and became the dominant programming paradigm in the 1990's. (source)
And many of us out here using OOP on a daily basis to get work done would love for TypeScript to fully embrace OOP instead of ignoring important aspects of it. We'd rather not have to use hacks to achieve very basic functionality.
Paul Shryock (@paulshryock) I wasn't giving an opinion, the only thing mine, was the hack.
And you were not disagreeing with me, because I also think there's nothing complex at all.
How do you or I know what most users will do?
Exactly, that's also what quotes meant there.
It's part sarcasam and part that's the team general sentiment when some feature doesn't get enough trackion or "convincing" reasons. Not my opinion.
Although I understand it's because it's their project, their budget and they decide what to do. (unless someday they make it free for anyone to PR whatever feature they'd like).
The problem is that you didn't understand well that sarcasm or the meaning of my quotation marks. My bad for being confusing.
We'd rather not have to use hacks to achieve very basic functionality.
Again, the hack is for the meantime, in case it was useful to anyone, as this issue is even closed and this feature isn't coming anytime soon. It was useful to me for instance, because I rather have a makeshift final than no final at all.
StephenColebourne recently had this talk (albeit for Java) in which he said
So the best practise here [with immutability] clearly is to favour immutability - final classes, final fields.. keep all the mutability you can, ideally, within a source file. So if you've got a source file and you need to do something mutable, keep the mutability within that file, and maybe really knock people on the head in code reviewing by naming the parameters and the variables "mutableSomething". It should be unusual, it shouldn't be the norm. If you can do that, you'll end up with the code that is simpler and better to use in multi-threading.
The entire thing is less than 50 minutes, and well worth a watch, but here's the link with the timestamp to the quoted section.
Going back to the comment about final being an "advanced" or "complex" feature if that was the implication, I'd say we can look at this two ways.
We can go the Java approach where naive implementations of a class don't use final because it wasn't thought about in an open-closed pattern way, but advanced developers will specifically design classes that are open for extension by making API methods public final.
So Java, like Javascript is non-final by default.
If we consider Kotlin though we don't have the final keyword. For references we get val vs var (like const vs let in Javascript), and for methods, they are final by default unless declared open.
Kotlin is a competitor to Typescript, and it just makes sense to use it instead of Typescript for larger codebases, for this reason. final in Typescript would at least upgrade Typescript to give advanced developers such as library authors some options.
Reacted by Klaus Reimer, neeko-cat, Ayfri, Paul Shryock and Edoardo Luppi
If we consider Kotlin though we don't have the final keyword. For references we get val vs var (like const vs let in Javascript), and for methods, they are final by default unless declared open.
Yes, final by default would be preferable. But if we can't have that (because Microsoft rejects it, or because it's considered too big of a breaking change by the community), then final as a possibility is pretty critical.
Reacted by Nathan Phillip Brink, Matej, Voltra and neeko-cat
Mohamed Hegazy (@mhegazy) ~9 years later, and after a considerable amount of feedback, can you consider reopening the issue? I feel there's enough points in here to justify taking another look.
Reacted by Ayfri, Voltra, Paul Shryock, Martin, a11delavar, dabund24, Thiago Delgado Pinto, xusimr97, Mubinet, neeko-cat and 4 more
On Fri, Dec 5, 2025, 7:21 PM Dave ***@***.***> wrote:
*dderiso* left a comment (microsoft/TypeScript#8306)
<#8306 (comment)>
I'm not sure I understand why *final* is so hotly debated.
Include Exclude
Pros Stronger layer separations Less programmer confusion More use of
modular code -> smaller codebases -> faster loads ?? Maybe keeps language
lean
Cons More work and documentation for TS maintainers Possibly slower
compilers Leaves a gap in the language specification that makes it feel
less mature than other OOP languages
—
Reply to this email directly, view it on GitHub
<#8306 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AHY5WGQNZ7PANATW5IVCWWD4AIANLAVCNFSM4CB7YM32U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TGNRRHA4DCNBQHA2Q>
.
You are receiving this because you commented.Message ID:
***@***.***>
import{Final}from'final-decorator';
@FinalclassFinalBase{keep(): void{}}classChildextendsFinalBase{// ❌ Class FinalBase is marked with @Final and cannot be extended.keep(): void{}}classFinalMethodBase{
@Finalkeep(): void{}}classChildOfFinalMethodBaseextendsFinalMethodBase{keep(): void{}// ❌ Method keep overrides a base method marked with @Final.}//// Not allowed//
@FinalclassFinalFinal{
@Final// ❌ Method-level @Final is redundant when the class is already marked with @Final.keep(): void{}}
@Final// ❌ Final is not allowed on abstract classes.abstractclassAbstractBase{abstractrun(): void;}
Activity
mhegazy commentedon Apr 26, 2016
a class with private constructor is not extendable. consider using this instead.
Zorgatone commentedon Apr 26, 2016
From what I recalled I was sure the compiler didn't like the private keyword on the constructor. Maybe I'm not using the paste version though
mhegazy commentedon Apr 26, 2016
This is a new feature, will be released in TS 2.0, but you can try it using
typescript@next. see #6885 for more details.Zorgatone commentedon Apr 26, 2016
Ok thank you
duanyao commentedon Apr 27, 2016
Doesn't private constructor also make a class not instantiatable out of the class? It's not a right answer to final class.
mhegazy commentedon May 17, 2016
Java and/or C# uses the
finalclass to optimize your class at runtime, knowing that it is not going to be specialized. this i would argue is the main value for final support. In TypeScript there is nothing we can offer to make your code run any better than it did without final.Consider using comments to inform your users of the correct use of the class, and/or not exposing the classes you intend to be final, and expose their interfaces instead.
0815fox commentedon Jun 20, 2016
I do not agree with that, instead I agree with duanyao. Private does not solve that issue, because I also want classes which are final to be instanciateable using a constructor. Also not exposing them to the user would force me to write additional factories for them. For me the main value of final support is, that it prevents users from making mistakes.
Arguing like that: What does TypeScript offer to make my code run faster, when I use types in function signatures? Isn't it also only for preventing users from making mistakes? I could write comments describing which types of values a user should pass in as a parameter. It's a pitty, that such extensions like a final keyword are just pushed away, because on my opinion it collides with the original intension of typescript: make JavaScript safer by adding a compilation level, which performs as many checks as possible to avoid as many mistakes upfront as possible. Or did I misunderstand the intention of TypeScript?
0815fox commentedon Jun 20, 2016
There should also be a
finalmodifier for methods:E.g. I often use following pattern, where I want to urgently avoid fooIt to be overridden:
mhegazy commentedon Jun 20, 2016
The argument about cost vs. utility is a fairly subjective one. The main concern is every new feature, construct, or keyword adds complexity to the language and the compiler/tools implementation. What we try to do in the language design meetings is to understand the trade offs, and only add new features when the added value out weights the complexity introduced.
The issue is not locked to allow members of the community to continue adding feedback. With enough feedback and compelling use cases, issues can be reopened.
mindarelus commentedon Aug 7, 2016
Actually final is very simple concept, does not add any complexity to the language and it should be added. At least for methods. It adds value, when a lot of people work on a big project, it is valuable not to allow someone to override methods, that shouldn't be overridden.
158 remaining items
paulshryock commentedon Jan 15, 2025
There is nothing advanced or complex about final classes or methods. This is basic fundamental object-oriented programming.
miguel-leon commentedon Jan 15, 2025
Well, that's what the quotes mean! Although, it's certainly more advanced than
var.Either way, that's all you got from the post? 🤦♂️ that's not the point, it is that "most users" won't make use of this and that's the "reasonable" expectation before implementing a feature.
Also, just showing a hack that can achieve the desired compilation error in the meantime. Which I'll be deleting since you're just a bunch of ungrateful ones.
paulshryock commentedon Jan 16, 2025
Miguel Leon (@miguel-leon), I'm sorry if I made you feel like your comment wasn't welcome. Your opinion is just as valid as mine.
I was disagreeing with part of what you said, and explaining why I disagreed. Disagreeing isn't a bad thing, is it? I like hearing opinions which are different than mine; that's how we all learn.
How do you or I know what most users will do? 🤷
I realize OOP isn't trendy on social media right now, and I probably won't find popular YouTubers writing final classes in their videos. But Object-Oriented Programming is a fundamental concept in Computer Science. It's been around since the 1950's, prominently-used since the 1970's and 1980's, and became the dominant programming paradigm in the 1990's. (source)
And many of us out here using OOP on a daily basis to get work done would love for TypeScript to fully embrace OOP instead of ignoring important aspects of it. We'd rather not have to use hacks to achieve very basic functionality.
miguel-leon commentedon Jan 16, 2025
Paul Shryock (@paulshryock) I wasn't giving an opinion, the only thing mine, was the hack.
And you were not disagreeing with me, because I also think there's nothing complex at all.
Exactly, that's also what quotes meant there.
It's part sarcasam and part that's the team general sentiment when some feature doesn't get enough trackion or "convincing" reasons. Not my opinion.
Although I understand it's because it's their project, their budget and they decide what to do. (unless someday they make it free for anyone to PR whatever feature they'd like).
The problem is that you didn't understand well that sarcasm or the meaning of my quotation marks. My bad for being confusing.
Again, the hack is for the meantime, in case it was useful to anyone, as this issue is even closed and this feature isn't coming anytime soon. It was useful to me for instance, because I rather have a makeshift
finalthan nofinalat all.mathmul commentedon Oct 29, 2025
Stephen Colebourne recently had this talk (albeit for Java) in which he said
The entire thing is less than 50 minutes, and well worth a watch, but here's the link with the timestamp to the quoted section.
nealeu commentedon Oct 29, 2025
Going back to the comment about final being an "advanced" or "complex" feature if that was the implication, I'd say we can look at this two ways.
We can go the Java approach where naive implementations of a class don't use final because it wasn't thought about in an open-closed pattern way, but advanced developers will specifically design classes that are open for extension by making API methods
public final.So Java, like Javascript is non-final by default.
If we consider Kotlin though we don't have the final keyword. For references we get val vs var (like const vs let in Javascript), and for methods, they are final by default unless declared
open.Kotlin is a competitor to Typescript, and it just makes sense to use it instead of Typescript for larger codebases, for this reason.
finalin Typescript would at least upgrade Typescript to give advanced developers such as library authors some options.paulshryock commentedon Oct 30, 2025
Yes,
finalby default would be preferable. But if we can't have that (because Microsoft rejects it, or because it's considered too big of a breaking change by the community), thenfinalas a possibility is pretty critical.neeko-cat commentedon Nov 3, 2025
Mohamed Hegazy (@mhegazy) ~9 years later, and after a considerable amount of feedback, can you consider reopening the issue? I feel there's enough points in here to justify taking another look.
dderiso commentedon Dec 5, 2025
I'm not sure I understand why final is so hotly debated.
EduApps-CDG commentedon Dec 6, 2025
paulshryock commentedon Dec 7, 2025
Because Microsoft.
Michota commentedon Feb 27, 2026
10 years later: nope.
Voltra commentedon Feb 28, 2026
If I get enough courage and free time on my hands, I'll check how they implement
abstractand implementfinalmyselfXample commentedon Mar 1, 2026
Voltra yes but your pr won’t be accepted and your work rolled back « Endgame ». You better convince ecma script to add final.
TiMESPLiNTER commentedon Mar 14, 2026
I implemented it myself using a decorator and ESLint rules, in case anyone is interested:
Decorator: https://www.npmjs.com/package/final-decorator
ESLint rules checking decorator: https://www.npmjs.com/package/eslint-plugin-final
Check the repo for how to use it: https://github.com/TiMESPLiNTER/ts-final