Errata

Programming TypeScript

Errata for Programming TypeScript

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
Printed, PDF, ePub, Mobi, , Other Digital Version
Page Functions
https://learning.oreilly.com/library/view/programming-typescript/9781492037644/ch04.html#function-overloads

In the type definition, you wrote the following type signature:

type WarnUser = {
(warning: string): void
wasCalled: boolean
}

After that, in the following code, you did not provide, wasCalled argument:

let warnUser: WarnUser = (warning: string) => {
if (warnUser.wasCalled) {
return
}
warnUser.wasCalled = true
alert(warning)
}
warnUser.wasCalled = false

It gives the following squiggly:
Property 'wasCalled' is missing in type '(warning: string) => void' but required in type 'WarnUser'.ts(2741)

I think you meant to declare wasCalled as an optional parameter in the type signature.

type WarnUser = {
(warning: string): void
wasCalled?: boolean
}

Note from the Author or Editor:
A typo on page 64 incorrectly assigns an explicit type annotation to the warnUser function, and claims that assigning an additional property to that function would not lead to a TypeError. This would have been correct, were it not for that explicit type annotation.

Corrected text is here: https://gist.github.com/bcherny/37bac064b151451f4858e0ae28d3ee5b.

Anonymous  Jun 05, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle location 3249
Footnote 4

A footnote says:

"A handful of languages — Scala, PHP, Kotlin, and Rust, to name a few — implement a pared-down version of mixins, called traits. Traits are like mixins, but don’t have constructors and don’t support instance properties."

I don't think "don't support instance properties" is actually a property of traits. PHP traits do support instance properties, for example.

Note from the Author or Editor:
PHP traits indeed support instance properties.

Traits vs. Mixins is a finicky topic, where implementations are all over the place, and rarely conform to the concepts as originally defined (Traits by Scharli et. al. in 2003, and Mixins by Bracha et. al. in his legendary 1990 paper).

Let's remove the footnote from this book ("A handful of... and the base class."), in order to take a more egalitarian view of Mixins vs. Traits: while they might differ on paper, they're often used interchangeably in practice.

Daniel Lo Nigro  Jun 14, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle location 5646
Under "Typesafe Multithreading" heading

"Since the Command type is a discriminated union type (see [[ discriminated unions]])"

"discriminated unions" looks like it's supposed to be link to another section of the book, instead of being written with brackets around it like " [[ discriminated unions]]"

Note from the Author or Editor:
This is a missing cross-reference. "[[discriminated unions]]" should be a cross-reference to the section on "Discriminated union types".

Daniel Lo Nigro  Jun 14, 2019  Aug 09, 2019
Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle location 6095
Using TSX with React heading, note 5

useState < number[] >;([])).

This code has a misplaced semicolon

Note from the Author or Editor:
This is indeed a typo. It should be changed from:

Before: (e.g., with useState<number[]>;([]))
After (backticks indicate code): (e.g., with `useState<number[]>([])`)

Daniel Lo Nigro  Jun 14, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page xvi
2nd para, last sentence + annotation of following code example

Original: "Thank you to O'Rielly"
Suggested fix: "Thank you to O'Reilly"

;)

Note from the Author or Editor:
We should change "O'Rielly" to "O'Reilly" -- I make this mistake too often to admit :)

Jørgen Lang  Jun 17, 2019  Apr 18, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle location 7239
Chapter 12, "Artifacts" heading, 2nd paragraph under table 12-1

"Chrome DevtTools" should be "Chrome DevTools"

Note from the Author or Editor:
Good catch! Indeed, "Chrome DevtTools" should be "Chrome DevTools".

Daniel Lo Nigro  Jun 27, 2019  Aug 09, 2019
Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle Location 2136
type MyEvent

In the following:

let myEvent: Event<HTMLButtonElement | null> = {
target: document.querySelector('#myButton'),
type: 'click'
}

Should the type 'Event' be 'MyEvent'?

Note from the Author or Editor:
Great catch - this should be “MyEvent”, rather than “Event”.

Mike Glaz  Aug 08, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle Location 2977
5.8 Mixins, debug() function within withEZDebug() function

With the code as is, the output, for me, of user.debug() is

Function({"id":3,"name":"Emma Gluzman"})

However, when I change the following line:

let Name = Class.constructor.name

to

let Name = this.constructor.name

then I get the following output:

HardToDebugUser({"id":3,"name":"Emma Gluzman"})

Was this the idea or is there a way for the output to actually be:

User({"id":3,"name":"Emma Gluzman"}) ?

Note from the Author or Editor:
This is a great catch! Let's make two minor updates:

1. On page 103, update `let Name = Class.constructor.name` to `let Name = this.constructor.name`
2. On page 104, update `user.debug() // evaluates to 'User({"id": 3, "name": "Emma Gluzman"})'` to `user.debug() // evaluates to 'HardToDebugUser({"id": 3, "name": "Emma Gluzman"})'`

Mike Glaz  Aug 12, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Kindle Location 4056
Companion Object Pattern

The following code from the book:

type Currency = {   
unit: 'EUR' | 'GBP' | 'JPY' | 'USD'   
value: number
}

let Currency = {   
DEFAULT: 'USD',   
from(value: number, unit = Currency.DEFAULT): Currency {     
return {unit, value}   
}
}

gives me the following errors:

index.ts(6,5): error TS7022: 'Currency' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

index.ts(8,23): error TS7022: 'unit' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.



But when I turn 'strict' mode off in tsconfig.json, then it compiles...

Note from the Author or Editor:
This is a really great catch. I made the mistake of compiling this without strict mode enabled.

The corrected code is here. Callouts should remain as-is: https://gist.github.com/bcherny/3e73b5c8da3c5a85ed1448c4a33222b8

Mike Glaz  Aug 15, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page Online Version
Step 1: Add TSC, Chapter 11

There is a `}` missing in:

Step 1: Add TSC of Chapter 11

```
{ "compilerOptions": { "allowJs": true}
```

Note from the Author or Editor:
Confirmed this is a typo. This may have regressed when we added syntax highlighting to JSON blocks. There's a missing closing brace, and indentation is incorrect in several places.

On page 237:

Before:

```
{
"compilerOptions": {
"allowJs": true
}
```

After:

```
{
"compilerOptions": {
"allowJs": true
}
}
```

Similarly, on page 238:

Before:

```
{
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
```

After:

```
{
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
}
```

And further down on page 238:

Before:

```
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noImplicitAny": false
}
```

After:

```
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noImplicitAny": false
}
}
```

Finally, on page 241:

Before:

```
{
"compilerOptions": {
"allowJs": false,
"checkJs": false
}
```

After:

```
{
"compilerOptions": {
"allowJs": false,
"checkJs": false
}
}
```

Joe Schroecker  Dec 26, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page App04/Extending a Module
Code annotation of `Module` example

In this example:
```
import 'react' 1

declare module 'react' { 2
interface Component<P, S> { 3
reducer(action: object, state: S): S 4
}
}
```

Annotation (1) after it says:
"We import 'react', switching our extension file into SCRIPT MODE, which we need to be in to consume a React module. Note that there are other ways we could have switched to script mode, like importing something else, exporting something, or exporting an empty object (export {})—we didn’t have to import 'react' specifically."

I believe since it's using a import, it's switching the extension into MODULE MODE?
At least that's how I understand this part in Chapter "Module Mode Versus Script Mode":
"does your file have any imports or exports? If so, it uses module mode; otherwise, it uses script mode."
?

Note from the Author or Editor:
Confirmed -- this is a typo. We should update each usage of "script mode" to "module mode" in the paragraph at the bottom of 280:

Before: We import 'react', switching our extension file into script mode, which we need to be in to consume a React module. Note that there are other ways we could have switched to script mode, like importing something else, exporting something, or exporting an empty object (export {})—we didn’t have to import 'react' specifically.

After: We import 'react', switching our extension file into module mode, which we need to be in to consume a React module. Note that there are other ways we could have switched to module mode, like importing something else, exporting something, or exporting an empty object (export {})—we didn’t have to import 'react' specifically.

Joe Schroecker  Dec 30, 2019 
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 27
anywhere / at the end of the page?

Consider the section describing the 'number' data type (chapter 3). Boris has already mentioned type literals in the previous section (about booleans) and reminded of them in this section as well. One of my first thoughts was that we could use NaN and Infinity as type literals. However, according to this link https://github.com/microsoft/TypeScript/issues/15135 we cannot do so, and since I was not the only one thinking about it, it might be worth mentioning this fact in subsequent editions of the book.

Note from the Author or Editor:
This is a great idea! Let's add a footnote:

Footnote: "At the time of writing, you can't use `NaN`, `Infinity`, or `-Infinity` as type literals."

Insert the footnote on page 22 (looking at the printed edition), after "that your value is a specific `number` (c)".

Octavian Nita  Jul 15, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 37
2nd paragraph

The following seems to imply that readonly arrays can still be modified.

"Note that while read-only arrays ... they are backed by regular JavaScript arrays. That means even small updates to an array result in having to copy the original array first."

How would I write code that updates a readonly array?

Note from the Author or Editor:
This is a good call out. Let's add an example of what I mean by "small updates". On page 37, let's update from:

Before: "That means even small updates to an array result in having to copy the original array first"
After: "That means even small updates to an array -- using spread (`...`), `.slice`, and so on -- result in having to copy the original array first"

Mark Volkmann  Aug 31, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 41
enum Color example

The book implies that the output of this code will be "#c10000", but it is undefined. It says "TypeScript lets you access enums both by value and by key".

enum Color {
Red = '#c10000',
Blue = '#007ac1',
Pink = 0xc10050,
White = 255
}

let c = Color[0];
console.log('bc =', bc); // undefined, not the string "#c10000"

I think I understand it now! When I saw Color[0] I thought that was access an enum value by an index. However, I think that is treated as a value. No such value exists, so I get undefined. Color[255] gives "white". This is no example like this in the book.

Note from the Author or Editor:
This is a great catch! Let's clarify the example, so it works both at compile time and at runtime. On page 41, in the code block:

Before: "let c = Color[0] // string"
After: "let c = Color[255] // string"

Let's be careful to make sure the "//" comments in that code block are still aligned after this change.

Mark Volkmann  Aug 31, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 54
Last sentence

"In other words, numbers is an iterator"

should read

"In other words, numbers is an iterable"

shouldn't it? Numbers is an iterable; it doesn't produce an actual iterator until you pass it to array spread, a for of loop, etc.

(sorry for the double post - I submitted with page 64 originally, not 54, which is correct. Please delete my original post if possible).

Note from the Author or Editor:
Accepted.

Before: "In other words, `numbers` is an iterator..."
After: "In other words, `numbers` is an iterable..."

Adam2004  Jun 12, 2019  Aug 09, 2019
Page 73
2nd Code Example

In the code example in question, the type of the Promise when not explicitly annotated is stated to be inferred to be {}, but in fact it is inferred to be of type unknown (as of version 4.6.4 of Typescript, which is the latest version at the time of writing).

Note from the Author or Editor:
Hey, thanks for the report! Fun fact: this is actually a fix the TypeScript team landed in response to this chapter of the book. See https://github.com/microsoft/TypeScript/issues/27288

Look for the updated error in the next edition of the book!

----

Edits to make:

1. In the code block, update "// Inferred as {}" to "// Inferred as unknown"
2. In the code block, update "// Error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint', or an enum type." to "// Error TS2571: Object is of type 'unknown'."
3. In the text below the code block, replace "{}" with "unknown" (using code font): "What gives? Why did TypeScript infer result to be {}? Because we didn’t give it enough information to work with—since TypeScript only uses the types of a generic function’s arguments to infer a generic’s type, it defaulted T to {}!" -> "What gives? Why did TypeScript infer result to be unknown? Because we didn’t give it enough information to work with—since TypeScript only uses the types of a generic function’s arguments to infer a generic’s type, it defaulted T to unknown!"

Jason Gero  May 10, 2022 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 85
bullet #2

In bullet #2 all references to 'Piece' should be changed to 'Position'.

Note from the Author or Editor:
Confirmed. We should update all instances of "Piece" in that bullet to "Position", keeping the code font.

Jeff Carbonneau  Jul 30, 2019  Aug 09, 2019
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 118
At the end of the general note

Hi,

The book says : "... it would have been perfectly safe to pass in an object that's a super-type of the expected type."

If I understood correctly, the book should have said: "a sub-type of the expected type.

But great job on the book anyway.

Note from the Author or Editor:
Confirmed, this is a typo in the note on page 118:

Before: "pass in an object that’s a supertype of the expected type"
After: "pass in an object that’s a subtype of the expected type"

Mathieu CHEREZE  Apr 19, 2020 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 139
last line of the page

Might the term "subtype" of the last line be "supertype"?

Note from the Author or Editor:
Confirmed, this should be "supertype". Let's take the opportunity to avoid this jargon, and use more common lingo instead. On page 139:

Before: "Returns a subtype of `Object`, with just the given `Keys`"
After: "Returns a subset of `Object`, with just the given `Keys`"

Let's also update the Description for Pick in the Type Utilities table on page 271:

Before: "A subtype of an object type, with a subset of its keys"
After: "A subset of an object type, with just the given keys"

Shinnichi Wada  May 05, 2020 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 145
Last paragraph of "Distributive Conditionals"

It is not true that without the distributive property, the Without type would resolve to never. Here's how it would simplify:

Without<boolean | number | string, boolean>
= (boolean | number | string) extends boolean ? never : (boolean | number | string)
= boolean | number | string

Note that boolean | number | string is not assignable to boolean, hence we follow the false path of the ternary operator.

Note from the Author or Editor:
Thank you for the correction! The suggestion is right.

On page 145:

Before: we would have ended up with `never`
After: we would have ended up with `boolean | number | string`

Alexander Grounds  Jan 14, 2020 
Page 168
1st Code Sample on Page

Class Some<T> extends the interface Option<T>, but since Option<T> is an interface, it cannot be extended, it can only be implemented, therefore the code should read "class Some<T> implements Option<T>".

Note from the Author or Editor:
Hey, thank you for taking the time to report this mistake. Funny it took so long to spot it :) Look for the fix in the next edition of Programming TypeScript, and hope you're enjoying the book!

Boris

-----

Edits to make: in the code example --

1. Update "class Some<T> extends Option<T>" to "class Some<T> implements Option<T>"
2. Update "class None extends Option<never>" to "class None implements Option<never>"

Jason Gero  May 22, 2022 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 202
last paragraph

"Files that contain JSX use the file extension .jsx".
should be
Files that contain JSX *can* use the file extension .jsx".

It works fine to use the file extension ".js" for files that contain JSX and many developers do that.

Note from the Author or Editor:
This is technically right -- people sometimes parse .js files using a JSX parser.

Let's change the language on page 202 from:

Before: "Files that contain JSX use the file extension"
After: "Files that contain JSX often use the file extension"

Mark Volkmann  Aug 31, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 208
last sentence on page

Original: […] and we used templateUrls and styleUrl to […].

Change:
templateUrls -> templateUrl (singular)
styleUrl -> styleUrls (plural)

Note from the Author or Editor:
Accepted! Let's update "templateUrls" to "templateUrl", and "styleUrl" to "styleUrls".

Jørgen Lang  Aug 16, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 283
last para

Original:

type
Head over to “The types Directive” on page 262 to learn more about the type directive.

Change to:

types
[…]

Explanation: directive name should be plural instead of singular.

Note from the Author or Editor:
Great catch!

Let's update "type" to "types" in the following places:

- [Page 283, bottom] "type" -> "types"
- [Page 283, bottom] "the type directive" -> "the types directive"
- [Page 284, table at the top] "type" -> "types"

Jørgen Lang  Aug 25, 2019 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 289
2nd, 3rd, and 4th paragraphs

On page 289, Paragraphs 2~4 have numbers labeled `5, 6, 7` pointing to code JSX definition on page 288.

The typo are as following.


5 JSX.IntrinsicAttributes points to 6 on Page 288.
6 JSX.IntrinsicClassAttributes points to 7 on Page 288.
7 JSX.LibraryManagedAttributes points to 5 on Page 288


You can check out my sketch describing the error above here.
https://i.imgur.com/csZl7js.jpg


-- Sung Kim

Note from the Author or Editor:
Accepted! On page 289, please change:

- Change the number for 5 (JSX.IntrinsicAttributes) to 6
- Change the number for 6 (JSX.IntrinsicClassAttributes) to 7
- Change the number for 7 (JSX.LibraryManagedAttributes) to 5
- Update the order of the bullets from JSX.IntrinsicAttributes, JSX.IntrinsicClassAttributes, JSX.LibraryManagedAttributes to JSX.LibraryManagedAttributes, JSX.IntrinsicAttributes, JSX.IntrinsicClassAttributes

Sung Kim  Aug 24, 2019