From a1c7c2493568473247f3f1e6c0e0df736cb38657 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Wed, 17 Jul 2024 12:41:29 +0100 Subject: [PATCH 1/6] Tweak to 04 --- book-content/chapters/04-essential-types-and-annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book-content/chapters/04-essential-types-and-annotations.md b/book-content/chapters/04-essential-types-and-annotations.md index f677303..1049599 100644 --- a/book-content/chapters/04-essential-types-and-annotations.md +++ b/book-content/chapters/04-essential-types-and-annotations.md @@ -205,7 +205,7 @@ function add(a, b) { `a` and `b` could be strings, booleans, or anything else. TypeScript can't know from the function body what type they're supposed to be. -So, when you're declaring a named function, their parameters always need annotations in TypeScript. +So, when you're declaring a function, their parameters always need annotations in TypeScript. ### The `any` Type From ab9caabb413692e3e1510430125b40b060b7875a Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Wed, 17 Jul 2024 12:41:49 +0100 Subject: [PATCH 2/6] Fixed toUpper --- book-content/chapters/04-essential-types-and-annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book-content/chapters/04-essential-types-and-annotations.md b/book-content/chapters/04-essential-types-and-annotations.md index 1049599..608d4b4 100644 --- a/book-content/chapters/04-essential-types-and-annotations.md +++ b/book-content/chapters/04-essential-types-and-annotations.md @@ -166,7 +166,7 @@ isReleased = "yes"; And also giving us autocomplete on the variable: ```ts -albumTitle.toUpper; // shows `toUpperCase` in autocomplete +albumTitle.toUpper // shows `toUpperCase` in autocomplete ``` This is an extremely powerful part of TypeScript. It means that you can mostly _not_ annotate variables and still have your IDE know what type things are. From b15322171ad34d92983b3fe571f87da50c775b5d Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 23 Jul 2024 12:14:12 +0100 Subject: [PATCH 3/6] Updated 05 and 04 --- .../04-essential-types-and-annotations.md | 1 + .../chapters/05-unions-literals-and-narrowing.md | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/book-content/chapters/04-essential-types-and-annotations.md b/book-content/chapters/04-essential-types-and-annotations.md index 608d4b4..a6a4340 100644 --- a/book-content/chapters/04-essential-types-and-annotations.md +++ b/book-content/chapters/04-essential-types-and-annotations.md @@ -166,6 +166,7 @@ isReleased = "yes"; And also giving us autocomplete on the variable: ```ts +// prettier-ignore albumTitle.toUpper // shows `toUpperCase` in autocomplete ``` diff --git a/book-content/chapters/05-unions-literals-and-narrowing.md b/book-content/chapters/05-unions-literals-and-narrowing.md index 72faf71..2741002 100644 --- a/book-content/chapters/05-unions-literals-and-narrowing.md +++ b/book-content/chapters/05-unions-literals-and-narrowing.md @@ -603,7 +603,21 @@ function validateUsername(username: string | null): boolean { } ``` -##### Option 5: Extract the check into its own variable +##### Option 5: Check for `null` directly + +Another option is to check for `null` directly: + +```typescript +function validateUsername(username: string | null): boolean { + if (username === null) { + return false; + } + + return username.length > 5; +} +``` + +##### Option 6: Extract the check into its own variable Finally, for readability and reusability purposes you could store the check in its own variable `isUsernameOK`. From 37bc7f7c7ca225e0592432bd8125519e17febdb2 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 23 Jul 2024 12:19:08 +0100 Subject: [PATCH 4/6] Added chapter 8 feedback --- book-content/chapters/08-classes.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/book-content/chapters/08-classes.md b/book-content/chapters/08-classes.md index 21d995d..d342e38 100644 --- a/book-content/chapters/08-classes.md +++ b/book-content/chapters/08-classes.md @@ -248,7 +248,7 @@ class Album { } ``` -The `#` syntax behaves the same as `private`, but it's a newer feature that's part of the ECMAScript standard. This means that it can be used in JavaScript as well as TypeScript. +The `#` syntax behaves the same as `private`, but it actually comes from JavaScript, not TypeScript. Attempting to access a `#`-prefixed property from outside of the class will result in a syntax error: @@ -263,7 +263,9 @@ const loopFindingJazzRecords = new Album(); console.log(loopFindingJazzRecords.#rating); // SyntaxError ``` -Attempting to cheat by accessing it with a dynamic string will return `undefined` - and still give a TypeScript error. +This would also fail at runtime, too! But TypeScript helps us catch this at compile time. + +Attempting to cheat by accessing it with a dynamic string won't fail at runtime. But it will return `undefined` - and still give a TypeScript error. ```ts twoslash // @errors: 7053 @@ -277,7 +279,7 @@ const loopFindingJazzRecords = new Album(); console.log(loopFindingJazzRecords["#rating"]); // Output: undefined ``` -So, if you want to ensure that a property is truly private, you should use the `#` syntax. +So, if you want to ensure that a property is private at runtime _and_ compile time, you should use the `#` syntax. ## Class Methods @@ -346,7 +348,7 @@ myObj.arrow(); // { location: 'Class' } myObj.method(); // { location: 'Object' } ``` -In the `arrow` method, `this` is bound to the instance of the class where it was defined. In the `method` method, `this` is bound to the object where it was called. +In the `arrow` method, `this` is bound to the instance of the class where it was defined. In the `method` method, `this` is bound to the object where it was called - which is the `myObj` object. This can be a bit of a gotcha when working with classes, whether in JavaScript or TypeScript. From dfde99b5b6211f028c6ee1ceec7576ca4cfc3967 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 23 Jul 2024 12:21:22 +0100 Subject: [PATCH 5/6] Slightly more weight applied to not using namespaces --- book-content/chapters/09-typescript-only-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book-content/chapters/09-typescript-only-features.md b/book-content/chapters/09-typescript-only-features.md index f27f368..ff5a6da 100644 --- a/book-content/chapters/09-typescript-only-features.md +++ b/book-content/chapters/09-typescript-only-features.md @@ -495,7 +495,7 @@ Imagine ES modules, with `import` and `export`, never existed. In this world, ev This is the world that TypeScript was born into. Module systems like CommonJS (`require`) and ES Modules (`import`, `export`) weren't popular yet. So, namespaces were a crucial way to avoid naming conflicts and organize your code. -But now that ES modules are widely supported, you should use them over namespaces. Namespaces have very little relevance in modern TypeScript code, with some exceptions which we'll explore in our chapter on global scopes. +But now that ES modules are widely supported, you should not use namespaces. Namespaces have very little relevance in modern TypeScript code, with some exceptions which we'll explore in our chapter on global scopes. ## When to Prefer ES vs. TS From 3e2fec84b405bf69b68cfd448a03d02a0bb7a4e7 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 23 Jul 2024 12:34:14 +0100 Subject: [PATCH 6/6] Improved 7 --- book-content/chapters/07-mutability.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book-content/chapters/07-mutability.md b/book-content/chapters/07-mutability.md index 2f6f5d1..3484ec6 100644 --- a/book-content/chapters/07-mutability.md +++ b/book-content/chapters/07-mutability.md @@ -137,7 +137,7 @@ TypeScript gives us an error below `albumAttributes` inside of the `updateStatus This is happening because TypeScript has inferred the `status` property as a `string` rather than the specific literal type `"on-sale"`. Similar to with `let`, TypeScript understands that the property could later be reassigned: ```typescript -albumAttributes.status = "new-release"; +albumAttributes.status = "not-valid"; ``` This is true even though the `albumAttributes` object was declared with `const`. We get the error when calling `updateStatus` because `status: string` can't be passed to a function that expects `status: "new-release" | "on-sale" | "staff-pick"`. TypeScript is trying to protect us from potential runtime errors.