Skip to content

Default compiler options #9642

Closed
Closed

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

  1. jods4 commented on Jul 12, 2016

    @jods4

    This is also the first thing I do when I start a TS project: create an empty tsconfig.json file 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.

  2. GauSim commented on Jul 12, 2016

    @GauSim

    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 :)

  3. jods4 commented on Jul 12, 2016

    @jods4

    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:

    Compiler option Default TS Profile
    strictNullChecks false true since "2.0"
  4. RyanCavanaugh commented on Jul 12, 2016

    @RyanCavanaugh
    Member

    The design intent of tsc --init was to create a tsconfig.json file 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

        "noImplicitReturns": false,
        "noImplicitThis": false,
        // etc

    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.

  5. jods4 commented on Jul 12, 2016

    @jods4

    Ryan Cavanaugh (@RyanCavanaugh) A better tsc --init is 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.

  6. mhegazy commented on Jul 13, 2016

    @mhegazy
    Contributor

    I also like my config files small but the pattern here is that they are getting more and more complex.

    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 --noImplicitAny and --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 --strictChecks in 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 --noImplictReturns be lumped in what about --noUnusedParameters and --noUnusedLocales..

    I will present this suggestion in the next desing meeting, and will see if there is enough support for it.

  7. Elephant-Vessel commented on Jul 13, 2016

    @Elephant-Vessel

    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.

  8. use-strict commented on Jul 13, 2016

    @use-strict
    Author

    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 any is bad and the number of PRs fixing creeping any-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 any instead of generics, using optional properties instead of unions of well-shaped interfaces, index signatures, hardcoded strings instead of enums/constants etc).

  9. Elephant-Vessel commented on Jul 14, 2016

    @Elephant-Vessel

    Mohamed Hegazy (@mhegazy)

    I understand the need to be more strict, and we do definitely recommend everybody to run with --noImplicitAny and --strictNullChecks, but i do not think we can force this on everyone just because we think it is the better way.

    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.

  10. RyanCavanaugh commented on Aug 22, 2016

    @RyanCavanaugh
    Member

    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").

    noImplicitAny
    strictNullChecks
    noUnusedLocals
    noUnusedParameters
    noImplicitReturns
    noImplicitThis
    noFallthroughCasesInSwitch
    
  11. jods4 commented on Aug 22, 2016

    @jods4

    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.

  12. 13 remaining items

  13. jods4 commented on Aug 30, 2016

    @jods4

    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.

  14. Elephant-Vessel commented on Aug 31, 2016

    @Elephant-Vessel

    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.

  15. modified the milestone: on Sep 21, 2016
  16. aluanhaddad commented on Jan 7, 2017

    @aluanhaddad
    Contributor

    This makes me wonder why tsc --init currently includes

        "exclude": [
            "node_modules"
        ]
    

    when excluding "exclude", no pun intended, results in better behavior for more users.

  17. mightyiam commented on Mar 3, 2017

    @mightyiam
    • 👍 "flag soup is no fun"
    • 👍 easy migration from JavaScript

    What is the middle path?

  18. jods4 commented on Mar 6, 2017

    @jods4

    Just noticed that apparently MS committed to adding a new --strict option 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 noFallthroughCasesInSwitch or noImplicitReturns), 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!

  19. mhegazy commented on Mar 7, 2017

    @mhegazy
    Contributor

    tsc --init should now default --strict to true. (see #14486)

  20. mhegazy commented on Mar 7, 2017

    @mhegazy
    Contributor

    jods (@jods4), --noUnusedParameters, --noUnusedLocals, --noImplicitReturns and --noFallThroughCaseInSwitch are more of style checks and not type checks; and thus depend on user preferences in general, that is why these were not included.

    --strict is intended to include additonal checks in the future.

  21. modified the milestones: TypeScript 2.3, on Mar 7, 2017
  22. mightyiam commented on Mar 7, 2017

    @mightyiam

    Awesome step forward, it seems. Thank you.

  23. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CommittedThe team has roadmapped this issueFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions