Skip to content

Commit 6e0a767

Browse files
committed
Update tsconfig and corresponding docs
Our generated blueprint was *years* out of date, and between the changes we made in the types over the last year or so and the guidance we have given in the TS RFCs we are now both *able* and *required* to set `strict: true` as well as to opt into `noUncheckedIndexedAccess` and to disable `allowSyntheticDefaultImports` and `esModuleInterop`. Additionally, this provided a nice opportunity to document the choices we have made so folks have something to latch onto when looking at the config we generate for them, and to update the config to target the current latest versions of the `target` and `module` fields.
1 parent 48bf736 commit 6e0a767

File tree

2 files changed

+70
-23
lines changed

2 files changed

+70
-23
lines changed

blueprint-files/ember-cli-typescript/tsconfig.json

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,68 @@
11
{
22
"compilerOptions": {
3-
"target": "es2020",
4-
"allowJs": true,
3+
"target": "ES2022",
4+
"module": "ES2022",
55
"moduleResolution": "node",
6-
"allowSyntheticDefaultImports": true,
7-
"noImplicitAny": true,
8-
"noImplicitThis": true,
9-
"alwaysStrict": true,
10-
"strictNullChecks": true,
11-
"strictPropertyInitialization": true,
6+
7+
// Trying to check Ember apps and addons with `allowJs: true` is a recipe
8+
// for many unresolveable type errors, because with *considerable* extra
9+
// configuration it ends up including many files which are *not* valid and
10+
// cannot be: they *appear* to be resolve-able to TS, but are in fact not in
11+
// valid Node-resolveable locations and may not have TS-ready types. This
12+
// will likely improve over time
13+
"allowJs": false,
14+
15+
// --- TS for SemVer Types compatibility
16+
// Strictness settings -- you should *not* change these: Ember code is not
17+
// guaranteed to type check with these set to looser values.
18+
"strict": true,
19+
"noUncheckedIndexedAccess": true,
20+
21+
// Interop: these are viral and will require anyone downstream of your
22+
// package to *also* set them to true. If you *must* enable them to consume
23+
// an upstream package, you should
24+
"allowSyntheticDefaultImports": false,
25+
"esModuleInterop": false,
26+
27+
// --- Lint-style rules
28+
29+
// You should feel free to change these, especially if you are already
30+
// covering them via linting (e.g. with @typescript-eslint).
1231
"noFallthroughCasesInSwitch": true,
1332
"noUnusedLocals": true,
1433
"noUnusedParameters": true,
1534
"noImplicitReturns": true,
35+
"noPropertyAccessFromIndexSignature": true,
36+
37+
// --- Compilation/integration settings
38+
// Setting `noEmitOnError` here allows ember-cli-typescript to catch errors
39+
// and inject them into Ember CLI's build error reporting, which provides
40+
// nice feedback for when
1641
"noEmitOnError": true,
42+
43+
// We use Babel for emitting runtime code, because it's very important that
44+
// we always and only use the same transpiler for non-stable features, in
45+
// particular decorators. If you were to change this to `true`, it could
46+
// lead to accidentally generating code with `tsc` instead of Babel, and
47+
// could thereby result in broken code at runtime.
1748
"noEmit": true,
49+
50+
// Ember makes heavy use of decorators; TS does not support them at all
51+
// without this flag.
52+
"experimentalDecorators": true,
53+
54+
// Support generation of source maps. Note: you must *also* enable source
55+
// maps in your `ember-cli-babel` config and/or `babel.config.js`.
56+
"sourceMap": true,
57+
"declaration": true,
58+
"declarationMap": true,
1859
"inlineSourceMap": true,
1960
"inlineSources": true,
61+
62+
// The combination of `baseUrl` with `paths` allows Ember's classic package
63+
// layout, which is not resolveable with the Node resolution algorithm, to
64+
// work with TypeScript.
2065
"baseUrl": ".",
21-
"module": "es6",
22-
"experimentalDecorators": true,
2366
"paths": <%= pathsFor(dasherizedPackageName) %>
2467
},
2568
"include": <%= includes %>

docs/ts/using-ts-effectively.md

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,28 @@ Some specific tips for success on the technical front:
88

99
First, use the _strictest_ strictness settings that our typings allow (currently all strictness settings except `strictFunctionTypes`). While it may be tempting to start with the _loosest_ strictness settings and then to tighten them down as you go, this will actually mean that "getting your app type-checking" will become a repeated process—getting it type-checking with every new strictness setting you enable—rather than something you do just once.
1010

11-
The full recommended _strictness_ settings in your `"compilerOptions"` hash:
11+
The full recommended _strictness_ settings in your `"compilerOptions"` hash (which are also the settings generated by the ember-cli-typescript blueprint):
1212

13-
```json
13+
```json5
1414
{
15-
"noImplicitAny": true,
16-
"noImplicitThis": true,
17-
"alwaysStrict": true,
18-
"strictNullChecks": true,
19-
"strictPropertyInitialization": true,
20-
"noFallthroughCasesInSwitch": true,
21-
"noUnusedLocals": true,
22-
"noUnusedParameters": true,
23-
"noImplicitReturns": true,
24-
"noUncheckedIndexedAccess": true,
15+
"compilerOptions": {
16+
// Strictness settings -- you should *not* change these: Ember code is not
17+
// guaranteed to type check with these set to looser values.
18+
"strict": true,
19+
"noUncheckedIndexedAccess": true,
20+
21+
// You should feel free to change these, especially if you are already
22+
// covering them via linting (e.g. with @typescript-eslint).
23+
"noFallthroughCasesInSwitch": true,
24+
"noUnusedLocals": true,
25+
"noUnusedParameters": true,
26+
"noImplicitReturns": true,
27+
"noPropertyAccessFromIndexSignature": true,
28+
}
2529
}
2630
```
2731

28-
A good approach is to start at your "leaf" files (the ones that don't import anything else from your app, only Ember types) and then work your way back inward toward the most core types that are used everywhere. Often the highest-value modules are your Ember Data models and any core services that are used everywhere else in the app – and those are also the ones that tend to have the most cascading effects (having to update _tons_ of other places in your app) when you type them later in the process.
32+
A good approach is to start at your "leaf" modules (the ones that don't import anything else from your app, only Ember or third-party types) and then work your way back inward toward the most core moduels that are used everywhere. Often the highest-value modules are your Ember Data models and any core services that are used everywhere else in the app – and those are also the ones that tend to have the most cascading effects (having to update _tons_ of other places in your app) when you type them later in the process.
2933

3034
Finally, leave `"noEmitOnError": true` (the default) in the `"compilerOptions"` hash in your `tsconfig.json`. This will fail your build if you have type errors, which gives you the fastest feedback as you add types.
3135

0 commit comments

Comments
 (0)