Repository navigation
Default compiler options #9642
Description
At the moment there are a bunch of opt-in compiler flags that are off by default. In most cases, they fix or add some behavior to the compilation that would have otherwise been a breaking change. This makes perfect sense for existing projects, but it shouldn't be default behavior for new ones.
IMHO, TS 2.0 would have been a good opportunity to turn some opt-in flags into opt-outs at least, if not removing them altogether. Avoiding breaking changes lead to a configuration nightmare where there are a dozen options doing similar things in slightly different manners. I hope you will take this into account for future releases.
For now my proposal would be to simply change the output of tsc --init. It won't affect users that create a tsconfig file from scratch, but it will at least give some useful defaults for the others, while keeping transparent what options were explicitly used.
Running tsc --init, yields this:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
},
"exclude": [
"node_modules"
]
}
Proposal:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"strictNullChecks": true
"sourceMap": false
},
"exclude": [
"node_modules"
]
}
My reasoning here is that new projects should have the stricter settings, because there is no legacy JavaScript code being migrated. The noImplicit* options make it easier to have good, type-safe code from the start, especially for new users, who don't understand the difference or see its advantages.
Activity
jods4 commentedon Jul 12, 2016
This is also the first thing I do when I start a TS project: create an empty
tsconfig.jsonfile and add a lot of compiler options. Even more than suggested above:noFallthroughCasesInSwitch suppressImplicitAnyIndexErrors skipDefaultLibCheck.Undeniably, with 50+ compiler options, setting up a project can be confusing and tedious for both newcomers and old-timers alike. Back-compat has its price.
Here's another idea that may help: introducing profiles. It would be a set of default options that can be defined with a single key -- which is good for people upgrading or not using
tsc --init. Of course, the profile can be overriden by specific options if you don't like a particular feature.Something like:
{ "compilerProfile": "2.0", "compilerOptions": { "module": "commonjs", "target": "es5", "sourceMap": false, } }What goes into a profile is debatable, but I would put all the language safety features by default.
GauSim commentedon Jul 12, 2016
With profiles it would be more "black magic voodoo" behind the stettings. To solve this you would have to have to maintain extra documentation that states out with profile has with values set by default, to understand what is being used. This adds a lot complexity.
I think this is more about finding and setting good default values to start of a project, so there is a little more guidance what is a good direction to go and then make it easy to change the settings to the need of the project if needed.
I total love the idea of having a little but stricter defaults, because introducing them afterwards always is pain :)
jods4 commentedon Jul 12, 2016
Simon Gausmann (@GauSim)
I don't know, I imagine them really simple: "2.0" is TS with all safety features released up to 2.0 turned on, "2.1" is the default profile when TS 2.1 comes out if it contains new backward-incompatible checks.
I certainly don't suggest a whole lot of "2.0-es5-amd" voodoo variations. Rather: if TS 2.0 was TS first release, which features would be turned on? This is "2.0" profile, this is what you should use by default. The only reason you need to opt-in is because of backward compatibility.
So at most, we should add to documentation when a feature was introduced. For example:
strictNullChecksfalsetruesince"2.0"RyanCavanaugh commentedon Jul 12, 2016
The design intent of
tsc --initwas to create atsconfig.jsonfile that runs the same as the commandline which created it, to provide an easy way to transition from commandline compilations to tsconfig-based compilations (since we're gradually introducing more and more things that are only available in tsconfig).A good compromise might be to include the property keys for the things we think people should seriously consider turning on. In other words, create a config file that contains
Sort of a "menu" of options that should be appetizing 🍔 🍕. Remembering the exact names and spellings (and even existence) of these options is pretty hard so lowering the barrier to entry might help a lot.
jods4 commentedon Jul 12, 2016
Ryan Cavanaugh (@RyanCavanaugh) A better
tsc --initis a good thing.I just wish we could cover more ground as this does not help people trying to upgrade an old project to the newer stuff, or people who don't use
tsc. Personnally I start with a blank file in VS (Code or normal).Spelling is not an issue for me thanks to the JSON schemas supported by both editors, but with the growing number of options it's getting more and more a memory exercise to find everything you want.
I also like my config files small but the pattern here is that they are getting more and more complex.
mhegazy commentedon Jul 13, 2016
I do not think there is much we can do here. It is the nature of things i presume. as a language evolves, new features have to be under flags to ensure our existing users do not suffer in the transition. I understand the need to be more strict, and we do definitely recommend everybody to run with
--noImplicitAnyand--strictNullChecks, but i do not think we can force this on everyone just because we think it is the better way.We have talked about an uper flag
--strictChecksin the past that lumps all these, but it is not clear if this will make things easier or worse, as users start to opt out of some of the strict checks, but not others, and you have to know what is included by default and what is not. for instance should--noImplictReturnsbe lumped in what about--noUnusedParametersand--noUnusedLocales..I will present this suggestion in the next desing meeting, and will see if there is enough support for it.
Elephant-Vessel commentedon Jul 13, 2016
Yay for nudging users towards a stricter use of typescript. Not only for their own benefit, but for the self interest of the typescript community as it will improve the general code base out there and provide a more focused typed model, where both of which will also probably make a better impression within the general software development community. Which matters.
In the spirit of treating the properly typed typescript as the default, there is also the possibility to negate these compiler settings and give users the possibility to explicitly opt in for a weaker type system, instead of implicitly being opted in into what should be the default.
So instead of
"noImplicitAny": false, we could have"implicitAny": true.That would also reduce the ts.config bloat for default configs for stricter TS.
use-strict commentedon Jul 13, 2016
Mohamed Hegazy (@mhegazy) , please also consider introducing breaking changes by changing the default value of the strictness options. While this sounds bad, existing users would only have problems when upgrading. Most should already keep a track of the roadmap and blog and have a good chance of learning about these changes and adjusting their config. After all, why/how would you be upgrading if you didn't know what was new in the first place?
On the other hand, new users, who just start learning the language, don't realize the difference and begin with bad habits, which not only hurts themselves but the community as well. I've lost count of the times I had to explain to beginners why
anyis bad and the number of PRs fixing creepingany-s in typings.Towards this goal, it would also be beneficial for the documentation to better explain type-safety and its advantages (intellisense, find references, safe refactoring) and common mistakes (e.g. using
anyinstead of generics, using optional properties instead of unions of well-shaped interfaces, index signatures, hardcoded strings instead of enums/constants etc).Elephant-Vessel commentedon Jul 14, 2016
Mohamed Hegazy (@mhegazy)
If having a default configuration is the same as forcing users into something, you will never get away from forcing the user one way or the other. If you don't want to "force" users to use a stricter configuration, your only alternative is to "force" them to use a laxer configuration.
You will never get away from the responsibility in providing a default configuration, so why not make is as good as possible?
If we play with our imagination and say that you update the default settings into a stricter mode continuously with each release as new settings mature, what negative consequences will come from this?
Worst case scenario, someone have to spend a couple of minutes of re-configuring the config if they haven't already specified the preference and really don't want the recommended settings.
On the positive side, new recommended features in regards of typing/strictness are clearly communicated and diversions from that requires an active choice from the user, which forces the user to at least be aware of what he/she is opting out from. People are very much nudgeable, and this will lead to a better knowledge and usage of the features of typescript, it will lead to generally better code in the wild and it will lead to more stable systems with less bugs in production.
Except from designing a great technical product with a lot of neat features, you also have the ability to influence and guide users, and to actively shape a knowledgeable and well informed community. The later is not insignificant.
RyanCavanaugh commentedon Aug 22, 2016
Approved to put more explicit options in the tsconfig, initialized with their current defaults (pictured: not our design philosophy).
Proposed list, welcoming feedback. We can also discuss ordering (listing them here in what I'd consider to be "most likely to be toggled on").
jods4 commentedon Aug 22, 2016
Ryan Cavanaugh (@RyanCavanaugh) I wish you would think about my suggestion above to introduce a "compatibility level" or "target version" or "profile" again. It is specifically not break all the things and has some advantages.
I did not come up with it, that's how .NET or SQL Server do it and it seems to work well enough for them, why not for you?
Your list is what I have in my current projects, with the addition of
suppressImplicitAnyIndexErrors.13 remaining items
jods4 commentedon Aug 30, 2016
Ryan Cavanaugh (@RyanCavanaugh) About migrating JS code, just sayin': with my proposal all it would take is remove
"target": "2.0"from your tsconfig and you're back at the most lax TS compiler there ever was. That's not very complicated.Or start without it and people who know better can just turn it on with a simple, predictable flag.
The current flag soup is no fun, and tends to become larger with each release.
Elephant-Vessel commentedon Aug 31, 2016
Ryan Cavanaugh (@RyanCavanaugh) Thank you, that makes much more sense. Wouldn't you say that this is actually less of an issue of a breaking change, and more of an issue regarding your unstated goal of making migration from javascript easier and less intimidating for beginners? The later seems like a valid goal, maybe it deserves to be explicit.
aluanhaddad commentedon Jan 7, 2017
This makes me wonder why
tsc --initcurrently includeswhen excluding
"exclude", no pun intended, results in better behavior for more users.mightyiam commentedon Mar 3, 2017
What is the middle path?
jods4 commentedon Mar 6, 2017
Just noticed that apparently MS committed to adding a new
--strictoption in upcoming 2.3, that by default enables most safety switches, and possibly future safety switches as well.See #14486, I guess it will close this issue 🎉
It's not all-inclusive (apparently it does not contain
noFallthroughCasesInSwitchornoImplicitReturns), which makes it a little awkward to know what's in there and what's not, but it contains all the important ones and it's a great step forward!mhegazy commentedon Mar 7, 2017
tsc --initshould now default--strictto true. (see #14486)mhegazy commentedon Mar 7, 2017
jods (@jods4),
--noUnusedParameters,--noUnusedLocals,--noImplicitReturnsand--noFallThroughCaseInSwitchare more of style checks and not type checks; and thus depend on user preferences in general, that is why these were not included.--strictis intended to include additonal checks in the future.mightyiam commentedon Mar 7, 2017
Awesome step forward, it seems. Thank you.