|
2 | 2 |
|
3 | 3 | ## Incremental adoption |
4 | 4 |
|
5 | | -If you are porting an existing app to TypeScript, you can install this addon and migrate your files incrementally by changing their extensions from `.js` to `.ts`. As TypeScript starts to find errors (and it usually does!), make sure to celebrate your wins – even if they're small! – with your team, especially if some people are not convinced yet. We would also love to hear your stories! |
| 5 | +If you are porting an existing app to TypeScript, you can install this addon and migrate your files incrementally by changing their extensions from `.js` to `.ts`. As TypeScript starts to find errors (and it usually does!), make sure to celebrate your wins—even if they're small!—with your team, especially if some people are not convinced yet. We would also love to hear your stories! |
6 | 6 |
|
7 | 7 | Some specific tips for success on the technical front: |
8 | 8 |
|
9 | | -* Use the _strictest_ strictness settings that our typings allow. 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. The only strictness setting you should turn _off_ is `strictFunctionTypes`, which our current type definitions do not support. The recommended _strictness_ settings in your `"compilerOptions"` hash: |
10 | | - |
11 | | - ```json |
12 | | - { |
13 | | - "noImplicitAny": true, |
14 | | - "noImplicitThis": true, |
15 | | - "alwaysStrict": true, |
16 | | - "strictNullChecks": true, |
17 | | - "strictPropertyInitialization": true, |
18 | | - "noFallthroughCasesInSwitch": true, |
19 | | - "noUnusedLocals": true, |
20 | | - "noUnusedParameters": true, |
21 | | - "noImplicitReturns": true |
22 | | - } |
23 | | - ``` |
| 9 | +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. |
| 10 | + |
| 11 | +The full recommended _strictness_ settings in your `"compilerOptions"` hash: |
| 12 | + |
| 13 | +```json |
| 14 | +{ |
| 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, |
| 25 | +} |
| 26 | +``` |
| 27 | + |
| 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. |
| 29 | + |
| 30 | +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. |
24 | 31 |
|
25 | | -* 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. |
26 | | -* Set `"noEmitOnError": true` in the `"compilerOptions"` hash in your `tsconfig.json` – it will help a lot if you can be sure that for the parts of your app you _have_ added types to are still correct. And you'll get nice feedback _immediately_ when you have type errors that way! |
| 32 | + |
27 | 33 |
|
28 | | -  |
| 34 | +## What about missing types? |
29 | 35 |
|
30 | | - _Note that this will **fail your build** if you have type errors._ This is generally preferable, but can sometimes be surprising. |
| 36 | +There are two schools of thought on how to handle things you don't have types for as you go: |
31 | 37 |
|
32 | | -* There are two schools of thought on how to handle things you don't have types for as you go: |
| 38 | +* Liberally use `any` for them and come back and fill them in later. This will let you do the strictest strictness settings but with an escape hatch that lets you say "We will come back to this when we have more idea how to handle it." This approach lets you move faster, but means you will still have lots of runtime type errors: `any` just turns the type-checker *off* for anything touching those modules. You’ll have to come back later and clean those up, and you’ll likely have more difficult refactorings to do at that time. |
33 | 39 |
|
34 | | - * Liberally use `any` for them and come back and fill them in later. This will let you do the strictest strictness settings but with an escape hatch that lets you say "We will come back to this when we have more idea how to handle it." |
35 | | - * Go more slowly, but write down at least minimally accurate types as you go. (This is easier if you follow the leaves-first strategy recommended above.) This is much harder, but allows you to have much higher confidence as you work through the app. |
| 40 | +* Go more slowly, but write down at least minimally accurate types as you go. (This is easier if you follow the leaves-first strategy recommended above.) This is much slower going, and can feel harder because you can’t just skip over things. Once you complete the work for any given module, though, you can be confident that everything is solid and you won’t have to revisit it in the future. |
36 | 41 |
|
37 | | - There is an inherent tradeoff between these two approaches; which works best will depend on your team and your app. |
| 42 | +There is an inherent tradeoff between these two approaches; which works best will depend on your team and your app. |
38 | 43 |
|
39 | 44 | ## Install other types! |
40 | 45 |
|
|
0 commit comments