question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Enable more linter checks in tsconfig.json by default

See original GitHub issue

🚀 Feature request

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Description

❯ npx @angular/cli@12 new web-apps --create-application false
❯ cd web-apps && yarn ng g app admin-console --routing --style scss

Currently, base tsconfig.json only contains strict, noImplicitReturns and noFallthroughCasesInSwitch flags

{
    "compileOnSave": false,
    "compilerOptions": {
      ...
      // all strict checks
      "strict": true,
      //  Linter checks
      "noImplicitReturns": true,
      "noFallthroughCasesInSwitch": true,
      ...
    }
}

Describe the solution you’d like

Enable new linter flags exposed by typescript in recent versions by defalt

{
  "compileOnSave": false,
  "compilerOptions": {
    ...
    // all strict checks
    "strict": true,
    //  Linter checks
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
	// TS 4.1
    "noUncheckedIndexedAccess": true,
	// TS 4.2
    "noPropertyAccessFromIndexSignature": true,
	// TS 4.3
    "noImplicitOverride": true,
	// TS 4.4
    "useUnknownInCatchVariables": true,
    "exactOptionalPropertyTypes": true,
    ...
  }
}
angular_strict_tsconfig_ts_4_4

Relevant blog posts:

Describe alternatives you’ve considered

I just have to add these flags manually to tsconfig.json

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
dgp1130commented, Jul 8, 2021

It is a good idea to consider updating our strictness with recent TypeScript versions. Although it is worth keeping in mind that npx typescript --init does not enable any of these by default. Only strict is enabled by default. Angular can probably be a bit more opinionated here, but we should take care to not diverge too much where there isn’t sufficient value to justify it.

After discussion within the tooling team, our takeaway with these flags is (interested to get @mgechev’s opinion as well):

noUncheckedIndexedAccess

This is really useful for objects and really annoying for arrays. having a[0] return an undefined type is awkward and particularly confusing to those who might be learning arrays for the first time. It also applies to array destructuring unless you type the object as a tuple [string, /* ... */] instead of an array string[]. Advanced users might understand the difference and be able to work around it, but this can easily trip up new devs.

The main benefit of catching possibly undefined properties in objects only applies when using index types which is a bit of anti-pattern IMHO, Map objects should be preferred where possible (or even a Record<string, T | undefined>).

As a result, we feel that the benefit for catching undefined properties in objects is outweighed by the awkwardness of using arrays and shouldn’t be included by default.

noPropertyAccessFromIndexSignature

We generally like this option as it is a pretty simple change which clarifies the user intent and catches possible typos without much friction. The error message is very straightforward and easily fixed. This should be included by default.

noImplicitOverride

The override keyword is really nice for catching accidental overrides that may not have been intentional. We think this is a good feature for the type system and very useful to have.

There were some concerns about this breaking a lot of existing documentation and education content already out there, however most Angular APIs do not use inheritance, so not much is actually broken. override is not required when implementing interfaces or abstract classes, so things like ngOnInit() are not affected by this option. As a result, users can define an Angular component, directive, service, etc. without running into a breakage. We couldn’t think of any Angular APIs that expect users extend an override a method. I’m sure some exist, but they are obscure enough to not be an issue for new devs getting started with Angular.

Our takeaway is that this doesn’t introduce much friction for new devs or existing educational content, so it is good to include by default.

useUnknownInCatchVariables

Using unknown in catch variables is more reflective of what the type system actually knows about a thrown object, but is often more annoying to use in practice. Throwing non-Error objects is generally considered an anti-pattern and should be avoided. Enabling this would also likely break almost all existing educational content which catches an error.

Our preference is for users to consider lint checks like no-throw-literal and treating any caught objects as Error. We think that would provide a better experience than useUnknownInCatchVariables.

exactOptionalPropertyTypes

This option draws a clear distinction between foo?: string and foo?: string | undefined which can be very confusing to new users. In particular, One particularly awkward edge case is that you can’t put a string | undefined value into an optional string type and the error message is very unhelpful in this regard.

interface Bar {
  bar?: string;
}
const baz = 'test' as string | undefined;

const bar: Bar = {
  bar: baz,
  // Type 'string | undefined' is not assignable to type 'string'.
  //     Type 'undefined' is not assignable to type 'string'.
};

This is a very nuanced option and will easily trip up even advanced developers who aren’t familiar with it. I think I saw somewhere that even the TypeScript team doesn’t recommend this unless you have a good reason for it in your project, but I’m not able to find that statement now. Our take is that this is too nuanced and specific, making it likely to cause more pain than it actually solves and shouldn’t be included by default.

Of course, all of these options can be manually added with minimal effort, this is only talking about what should be included by default for ng new projects. In total, this means that noPropertyAccessFromIndexSignature and noImplicitOverride should be added to ng new. We should also gate these so they are not included when --nostrict is provided, since the user wouldn’t want them in that case anyways (and I think they both require strictNullChecks regardless).

These should be added in the next major to reduce breakages of existing educative content (please please please, pin the versions of any tutorials or workshops you own specifically to avoid breakages from stuff like this). TS 4.3 should be the minimum by Angular v13, so it should be safe to include those two without worrying about older TypeScript versions that don’t support these flags.

I would love to migrate existing projects with the same options, however there don’t appear to be any existing codemods which do this. VSCode can fix all noImplicitOverride and noPropertyAccessFromIndexSignature errors in a file, and both are pretty precise fixes, so migrating a project should be relatively easily, even if not done automatically. We’ll probably skip existing projects on this for now and let them migrate themselves.

0reactions
angular-automatic-lock-bot[bot]commented, Sep 10, 2021

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TSConfig Reference - Docs on every TSConfig option
Setting the value to undefined will allow most JavaScript runtime checks for the ... will look for files starting at the same folder...
Read more >
Understanding TypeScript Configuration Options
allowUmdGlobalAccessLinter Checks ... Install typescript and generate tsconfig.json : $ npm init ... For more description, you can see the docs.
Read more >
How to use ESLint with TypeScript | Khalil Stemmler
ESLint is a JavaScript linter that enables you to enforce a set of ... In your project package.json , lets add a lint...
Read more >
no-unused-variable is deprecated; but I'm not using this config ...
Since TypeScript 2.9. Please use the built-in compiler checks instead. But my tsconfig.json does not seem to use this. { ...
Read more >
Linting in TypeScript using ESLint and Prettier - LogRocket Blog
This will generate a default TypeScript configuration file; Create a file called tsconfig.json at the root directory of your project and include ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found