You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book-content/chapters/02-ide-superpowers.md
+47-64Lines changed: 47 additions & 64 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,19 +101,14 @@ Sometimes TypeScript will warn you about things that will definitely fail at run
101
101
102
102
For example, consider the following code:
103
103
104
-
```typescript
104
+
```ts twoslash
105
+
// @errors: 18047
105
106
const a =null;
106
107
107
-
a.toString(); // red squiggly line under `a`
108
-
```
109
-
110
-
TypeScript tells us that there is a problem with `a`. Hovering over it shows the following error message:
111
-
112
-
```
113
-
'a' is possibly 'null'.
108
+
a.toString();
114
109
```
115
110
116
-
This tells us where the problem is, but it doesn't necessarily tell us what the problem is. In this case, we need to stop and think about why we can't call `toString()` on `null`. If we do, it will throw an error at runtime.
111
+
TypeScript tells us that there is a problem with `a`. This tells us where the problem is, but it doesn't necessarily tell us what the problem is. In this case, we need to stop and think about why we can't call `toString()` on `null`. If we do, it will throw an error at runtime.
117
112
118
113
```
119
114
Uncaught TypeError: Cannot read properties of null (reading 'toString').
@@ -127,10 +122,11 @@ Not everything TypeScript warns us about will actually fail at runtime.
127
122
128
123
Take a look at this example where we're assigning a property to an empty object:
129
124
130
-
```typescript
125
+
```ts twoslash
126
+
// @errors: 2339
131
127
const obj = {};
132
128
133
-
const result =obj.foo;// red squiggly line under `foo`
129
+
const result =obj.foo;
134
130
```
135
131
136
132
TypeScript draws a red squiggly line below `foo`. But if we think about it, this code won't actually cause an error at runtime. We're trying to assign a property that doesn't exist in this object: `foo`. This won't error, it will just mean that result is undefined.
@@ -141,37 +137,28 @@ It's best to think of TypeScript's rules as opinionated. They are a collection o
141
137
142
138
### Warnings Close to the Source of the Problem
143
139
144
-
<!-- TODO Consider moving this and the next section to later, perhaps the weird parts -->
145
-
146
140
TypeScript will try to give you warnings as close to the source of the problem as possible.
147
141
148
142
Let's take a look at an example.
149
143
150
-
```typescript
144
+
```ts twoslash
145
+
// @errors: 2561
151
146
typeAlbum= {
152
147
artist:string;
153
148
title:string;
154
149
year:number;
155
150
};
156
151
157
152
const album:Album= {
158
-
artsist: "Television",// red squiggly line under `artsist`
153
+
artsist: "Television",
159
154
title: "Marquee Moon",
160
155
year: 1977,
161
156
};
162
157
```
163
158
164
159
We define an 'Album' type - an object with three properties. Then, we say that const album needs to be of that type via `const album: Album`. Don't worry if you don't understand all the syntax yet - we'll cover it all later.
165
160
166
-
Can you see the problem? There's a typo of the `artist` property when creating an album. Hovering over `artsist` shows the following error message:
167
-
168
-
```
169
-
Type '{ artsist: string; title: string; year: number; }' is not assignable to type 'Album'.
170
-
171
-
Object literal may only specify known properties, but 'artsist' does not exist in type 'Album'. Did you mean to write 'artist'?
172
-
```
173
-
174
-
That's because we've said that the `album` variable needs to be of type `Album`, but we've misspelled `artist` as `artsist`. TypeScript is telling us that we've made a mistake, and even suggests the correct spelling.
161
+
Can you see the problem? There's a typo of the `artist` property when creating an album. That's because we've said that the `album` variable needs to be of type `Album`, but we've misspelled `artist` as `artsist`. TypeScript is telling us that we've made a mistake, and even suggests the correct spelling.
175
162
176
163
### Dealing With Multi-Line Errors
177
164
@@ -193,26 +180,28 @@ Don't worry about the syntax for now - we'll cover it later. The important thing
193
180
194
181
Now, let's call `logUserJobTitle` with a user object where the `job.title` is a number, not a string.
195
182
196
-
```typescript
183
+
```ts twoslash
184
+
// @errors: 2345
185
+
const logUserJobTitle = (user: {
186
+
job: {
187
+
title:string;
188
+
};
189
+
}) => {
190
+
console.log(user.job.title);
191
+
};
192
+
193
+
// ---cut---
197
194
const exampleUser = {
198
195
job: {
199
196
title: 123,
200
197
},
201
198
};
202
199
203
-
logUserJobTitle(exampleUser);// red squiggly line under `exampleUser`
200
+
logUserJobTitle(exampleUser);
204
201
```
205
202
206
203
It might seem like TypeScript should give us an error on `title` in the `exampleUser` object. But instead, it gives us an error on the `exampleUser` variable itself.
207
204
208
-
Hovering over `exampleUser` shows the following error message:
209
-
210
-
```
211
-
Argument of type '{ job: { title: number; }; }' is not assignable to parameter of type '{ job: { title: string; }; }'.
212
-
The types of 'job.title' are incompatible between these types.
213
-
Type 'number' is not assignable to type 'string'.
214
-
```
215
-
216
205
It's multiple lines long, which can feel pretty scary. A good rule of thumb with multi-line errors is to start at the bottom:
217
206
218
207
```
@@ -239,12 +228,9 @@ You can hover over more than just error messages. Any time you hover over a vari
239
228
240
229
In this example, we could hover over `thing` and see that it's of type `number`:
241
230
242
-
```typescript
231
+
```ts twoslash
243
232
let thing =123;
244
-
245
-
// hovering over `thing` shows:
246
-
247
-
let thing:number;
233
+
// ^?
248
234
```
249
235
250
236
Hovering works for more involved examples as well. Here `otherObject` spreads in the properties of `otherThing` as well as adding `thing`:
@@ -256,28 +242,30 @@ let otherThing = {
256
242
257
243
const otherObject = {
258
244
...otherThing,
259
-
thing,
245
+
thing: "abc",
260
246
};
261
247
262
248
otherObject.thing;
263
249
```
264
250
265
251
Hovering over `otherObject` will give us a computed readout of all of its properties:
266
252
267
-
```typescript
268
-
// hovering over `otherObject` shows:
269
-
270
-
const otherObject: {
271
-
thing:number;
272
-
name:string;
253
+
```ts twoslash
254
+
let otherThing = {
255
+
name: "Alice",
273
256
};
274
-
```
275
257
276
-
Depending on what you hover over, VS Code will show you different information. For example, hovering over `.thing` in `otherObject.thing` will show you the type of `thing`:
258
+
const otherObject = {
259
+
...otherThing,
260
+
thing: "abc",
261
+
};
277
262
263
+
// ---cut---
264
+
console.log(otherObject);
265
+
// ^?
278
266
```
279
-
(property) thing: number
280
-
```
267
+
268
+
Depending on what you hover over, VS Code will show you different information. For example, hovering over `otherObject` will show you all of its properties, while hovering over `thing` will show you its type.
281
269
282
270
Get used to the ability to float around your codebase introspecting variables and declarations, because it's a great way to understand what the code is doing.
283
271
@@ -287,8 +275,9 @@ Get used to the ability to float around your codebase introspecting variables an
287
275
288
276
In this code snippet we're trying to grab an element using `document.getElementById` with an ID of `12`. However, TypeScript is complaining.
289
277
290
-
```javascript
291
-
let element =document.getElementById(12); // red squiggly line under 12
278
+
```ts twoslash
279
+
// @errors: 2345
280
+
let element =document.getElementById(12);
292
281
```
293
282
294
283
How can hovering help to determine what argument `document.getElementById` actually requires? And for a bonus point, what type is `element`?
@@ -311,17 +300,12 @@ In the case of `getElementById`, we can see that it requires a string as an argu
311
300
312
301
This tells us that we can fix the error by changing the argument to a string:
313
302
314
-
```typescript
303
+
```ts twoslash
315
304
let element =document.getElementById("12");
305
+
// ^?
316
306
```
317
307
318
-
We also know that `element`'s type will be what `document.getElementById` returns, which we can confirm by hovering over `element`:
319
-
320
-
```typescript
321
-
// hovering over element shows:
322
-
323
-
const element:HTMLElement|null;
324
-
```
308
+
We also know that `element`'s type will be what `document.getElementById` returns, which we can confirm by hovering over `element`.
325
309
326
310
So, hovering in different places reveals different information. When I'm working in TypeScript, I hover constantly to get a better sense of what my code is doing.
327
311
@@ -432,8 +416,6 @@ A TypeScript-enabled feature called 'Rename Symbol' allows you to do that with a
432
416
433
417
Let's take a look at an example.
434
418
435
-
<!-- We could convert this to an exercise? -->
436
-
437
419
```typescript
438
420
const filterUsersById = (id:string) => {
439
421
returnusers.filter((user) =>user.id===id);
@@ -466,8 +448,9 @@ VS Code also offers a "Quick Fix" feature that can be used to run quick refactor
466
448
467
449
To open the Quick Fix menu, hit `Command + .`. If you do this on a line of code which references a value that hasn't been imported yet, a popup will show.
468
450
469
-
```typescript
470
-
const triangle =newTriangle(); // red squiggly line under `Triangle`
451
+
```ts twoslash
452
+
// @errors: 2552
453
+
const triangle =newTriangle();
471
454
```
472
455
473
456
One of the options in the Quick Fix menu will be 'Add All Missing Imports'. Selecting this option will add all the missing imports to the top of the file.
0 commit comments