From 81bf7265786d8f66fa30867fe25ba16f6b6eb2b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BB=BF=E6=9E=97?= <lvaluesilence@gmail.com>
Date: Fri, 11 Aug 2023 13:09:50 +0800
Subject: [PATCH 001/120] Update function.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

docs:delete「虽然」
---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index 5789eed..7fb4e5f 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -266,7 +266,7 @@ f(); // OK
 f(10); // OK
 ```
 
-上面示例中,虽然参数`x`后面有问号,表示该参数可以省略。
+上面示例中,参数`x`后面有问号,表示该参数可以省略。
 
 参数名带有问号,表示该参数的类型实际上是`原始类型|undefined`,它有可能为`undefined`。比如,上例的`x`虽然类型声明为`number`,但是实际上是`number|undefined`。
 

From b66402aaf61e1120a5ee598df3dedad0ca547930 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Fri, 11 Aug 2023 14:01:03 +0800
Subject: [PATCH 002/120] =?UTF-8?q?docs:=20=E5=8E=BB=E9=99=A4(),=20?=
 =?UTF-8?q?=E4=B8=8D=E7=84=B6=E4=BC=9A=E6=9C=89=E7=90=86=E8=A7=A3(|)?=
 =?UTF-8?q?=E6=95=B4=E4=BD=93=E4=B8=8E[]=E7=9A=84=E4=BC=98=E5=85=88?=
 =?UTF-8?q?=E7=BA=A7=E6=AF=94=E8=BE=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/array.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/array.md b/docs/array.md
index e3c34d6..0f0944e 100644
--- a/docs/array.md
+++ b/docs/array.md
@@ -24,7 +24,7 @@ let arr:(number|string)[];
 
 上面示例中,数组`arr`的成员类型是`number|string`。
 
-这个例子里面的圆括号是必须的,否则因为竖杠(`|`)的优先级低于`[]`,TypeScript 会把`number|string[]`理解成`number`和`string[]`的联合类型。
+这个例子里面的圆括号是必须的,否则因为竖杠`|`的优先级低于`[]`,TypeScript 会把`number|string[]`理解成`number`和`string[]`的联合类型。
 
 如果数组成员可以是任意类型,写成`any[]`。当然,这种写法是应该避免的。
 

From 839bbf9cf8ad793a519da462eaced8ca385412a6 Mon Sep 17 00:00:00 2001
From: why <w.why@163.com>
Date: Fri, 11 Aug 2023 15:26:23 +0800
Subject: [PATCH 003/120] =?UTF-8?q?fix:=20class.md=20=20=E7=AC=94=E8=AF=AF?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/class.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/class.md b/docs/class.md
index c6ab412..fd43c99 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -278,7 +278,7 @@ class MyClass {
 }
 ```
 
-属性存取器等同于方法,也必须包括在属性索性里面。
+属性存取器等同于方法,也必须包括在属性索引里面。
 
 ```typescript
 class MyClass {

From be3ace31d69dc6a70cb93cc4bfd2894aa1922c7e Mon Sep 17 00:00:00 2001
From: why <w.why@163.com>
Date: Fri, 11 Aug 2023 15:40:47 +0800
Subject: [PATCH 004/120] Update class.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

实例代码,与文字说明不一至处理
---
 docs/class.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index fd43c99..b7db13b 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -539,12 +539,12 @@ class Car implements MotorVehicle {
 }
 
 // 写法一
-const c:Car = new Car();
+const c1:Car = new Car();
 // 写法二
-const c:MotorVehicle = new Car();
+const c2:MotorVehicle = new Car();
 ```
 
-上面示例中,变量`c`的类型可以写成类`Car`,也可以写成接口`MotorVehicle`。它们的区别是,如果类`Car`有接口`MotoVehicle`没有的属性和方法,那么只有变量`c1`可以调用这些属性和方法。
+上面示例中,变量的类型可以写成类`Car`,也可以写成接口`MotorVehicle`。它们的区别是,如果类`Car`有接口`MotoVehicle`没有的属性和方法,那么只有变量`c1`可以调用这些属性和方法。
 
 作为类型使用时,类名只能表示实例的类型,不能表示类的自身类型。
 

From 11b4705d8f0749bb3589b54dca87521f34bb100c Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Fri, 11 Aug 2023 18:55:40 +0800
Subject: [PATCH 005/120] docs(any): fixed #25

---
 docs/any.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/any.md b/docs/any.md
index ce62426..8af7293 100644
--- a/docs/any.md
+++ b/docs/any.md
@@ -85,7 +85,7 @@ x = { foo: 'hello' };
 
 由于这个原因,建议使用`let`和`var`声明变量时,如果不赋值,就一定要显式声明类型,否则可能存在安全隐患。
 
-`const`命令没有这个问题,因为 TypeScript 要求`const`声明变量时,必须同时进行初始化(赋值)。
+`const`命令没有这个问题,因为 JavaScript 语言规定`const`声明变量时,必须同时进行初始化(赋值)。
 
 ```typescript
 const x; // 报错

From 1b37acc09848076531147b20858c2e276d75b21f Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Fri, 11 Aug 2023 19:21:56 +0800
Subject: [PATCH 006/120] docs(decorator): fixed typo

---
 docs/decorator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/decorator.md b/docs/decorator.md
index 52d8217..70ea454 100644
--- a/docs/decorator.md
+++ b/docs/decorator.md
@@ -719,7 +719,7 @@ accessor 装饰器的类型如下。
 type ClassAutoAccessorDecorator = (
   value: {
     get: () => unknown;
-    set(value: unknown) => void;
+    set: (value: unknown) => void;
   },
   context: {
     kind: "accessor";

From fbb32136cb1c7a09c47d4b98523fc0c676b47e8a Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Fri, 11 Aug 2023 19:54:41 +0800
Subject: [PATCH 007/120] docs(operator): modify infer

---
 docs/operator.md | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/docs/operator.md b/docs/operator.md
index 6d09145..2f35583 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -285,7 +285,7 @@ type Person = {
 type T = Person['age'|'name'];
 
 // number|string|boolean
-type A = Person[keyof Obj];
+type A = Person[keyof Person];
 ```
 
 上面示例中,方括号里面是属性名的联合类型,所以返回的也是对应的属性值的联合类型。
@@ -444,11 +444,9 @@ type Flatten<Type> =
   Type extends Array<infer Item> ? Item : Type;
 ```
 
-上面示例中,`Type`是外部传入的类型参数,如果它是数组`Array<T>`的子类型,那么就将类型变量`Item`推断为`T`,即`Item`代表数组的成员类型,写成`infer Item`,表示`Item`这个类型参数是从当前信息中推断出来的。
+上面示例中,`infer Item`表示`Item`这个参数是 TypeScript 自己推断出来的,不用显式传入,而`Flatten<Type>`则表示`Type`这个类型参数是外部传入的。`Type extends Array<infer Item>`则表示,如果参数`Type`是一个数组,那么就将该数组的成员类型推断为`Item`,即`Item`是从`Type`推断出来的。
 
-一旦定义了`Item`,后面的代码就可以使用这个类型参数了。
-
-下面是上例的泛型`Flatten<Type>`的用法。
+一旦使用`Infer Item`定义了`Item`,后面的代码就可以直接调用`Item`了。下面是上例的泛型`Flatten<Type>`的用法。
 
 ```typescript
 // string
@@ -458,7 +456,7 @@ type Str = Flatten<string[]>;
 type Num = Flatten<number>;
 ```
 
-上面示例中,第一个例子`Flatten<string[]>`传入的类型参数是`string[]`,可以推断出`Item`的类型是`string`,所以返回的是`string`。第二个例子`Flatten<number>`传入的类型参数是`number`,它不是数组的子类型,所以直接返回自身。
+上面示例中,第一个例子`Flatten<string[]>`传入的类型参数是`string[]`,可以推断出`Item`的类型是`string`,所以返回的是`string`。第二个例子`Flatten<number>`传入的类型参数是`number`,它不是数组,所以直接返回自身。
 
 如果不用`infer`定义类型参数,那么就要传入两个类型参数。
 
@@ -467,7 +465,7 @@ type Flatten<Type, Item> =
   Type extends Array<Item> ? Item : Type;
 ```
 
-上面是不用`infer`的写法,每次使用`Fleatten`的时候,都要传入两个参数,就比较麻烦。
+上面是不使用`infer`的写法,每次调用`Fleatten`的时候,都要传入两个参数,就比较麻烦。
 
 下面的例子使用`infer`,推断函数的参数类型和返回值类型。
 

From 011e715c4efd00d93b709c5c505a75cf823d6afd Mon Sep 17 00:00:00 2001
From: biubiubiu999 <houshengaaa@gmail.com>
Date: Fri, 11 Aug 2023 23:06:55 +0800
Subject: [PATCH 008/120] =?UTF-8?q?=E8=BF=99=E9=87=8Cv3=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E5=BA=94=E8=AF=A5=E6=98=AF=E8=A6=81=E7=A4=BA=E4=BE=8B=E4=B8=80?=
 =?UTF-8?q?=E4=B8=AAboolean=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/any.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/any.md b/docs/any.md
index 8af7293..6026996 100644
--- a/docs/any.md
+++ b/docs/any.md
@@ -237,7 +237,7 @@ function f():never {
 
 let v1:number = f(); // 不报错
 let v2:string = f(); // 不报错
-let v3:string = f(); // 不报错
+let v3:boolean = f(); // 不报错
 ```
 
 上面示例中,函数`f()`会抛错,所以返回值类型可以写成`never`,即不可能返回任何值。各种其他类型的变量都可以赋值为`f()`的运行结果(`never`类型)。

From e4a8092ecda7b55c62e351e4e9fdbb891d62d410 Mon Sep 17 00:00:00 2001
From: Ikko Eltociear Ashimine <eltociear@gmail.com>
Date: Sat, 12 Aug 2023 02:34:38 +0900
Subject: [PATCH 009/120] docs: fix typo in interface.md

inteface -> interface
---
 docs/interface.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/interface.md b/docs/interface.md
index dc8730f..a1b7c7f 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -322,7 +322,7 @@ interface CountryWithPop extends Country {
 
 ### interface 继承 class
 
-inteface 还可以继承 class,即继承该类的所有成员。关于 class 的详细解释,参见下一章。
+interface 还可以继承 class,即继承该类的所有成员。关于 class 的详细解释,参见下一章。
 
 ```typescript
 class A {
@@ -613,7 +613,7 @@ const obj:A = {
 
 上面示例中,`interface`把类型`A`的两个定义合并在一起。
 
-这表明,inteface 是开放的,可以添加属性,type 是封闭的,不能添加属性,只能定义新的 type。
+这表明,interface 是开放的,可以添加属性,type 是封闭的,不能添加属性,只能定义新的 type。
 
 (4)`interface`不能包含属性映射(mapping),`type`可以,详见《映射》一章。
 

From 925339d495046f83a4fc254da5ba0fd85274d996 Mon Sep 17 00:00:00 2001
From: Ayaka <26200808+KiritaniAyaka@users.noreply.github.com>
Date: Sun, 13 Aug 2023 21:00:07 +0800
Subject: [PATCH 010/120] fix: typo in function.md

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index 7fb4e5f..c489540 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -413,7 +413,7 @@ function sum(
 }
 ```
 
-参数结构可以结合类型别名(type 命令)一起使用,代码会看起来简洁一些。
+参数解构可以结合类型别名(type 命令)一起使用,代码会看起来简洁一些。
 
 ```typescript
 type ABC = { a:number; b:number; c:number };

From 930b3313b838da3d7ea35a3f675af2367c817cd2 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 14 Aug 2023 12:06:29 +0800
Subject: [PATCH 011/120] docs(types): fixed #30 Symbol wrapper object

---
 docs/types.md | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/docs/types.md b/docs/types.md
index 10977a8..c7a618f 100644
--- a/docs/types.md
+++ b/docs/types.md
@@ -235,7 +235,14 @@ Math.abs(n2) // 报错
 
 上面示例中,`Math.abs()`方法的参数类型被定义成小写的`number`,传入大写的`Number`类型就会报错。
 
-上一小节说过,`Symbol()`和`BigInt()`这两个函数不能当作构造函数使用,所以没有办法直接获得 symbol 类型和 bigint 类型的包装对象,因此`Symbol`和`BigInt`这两个类型虽然存在,但是完全没有使用的理由。
+上一小节说过,`Symbol()`和`BigInt()`这两个函数不能当作构造函数使用,所以没有办法直接获得 symbol 类型和 bigint 类型的包装对象,除非使用下面的写法。但是,它们没有使用场景,因此`Symbol`和`BigInt`这两个类型虽然存在,但是完全没有使用的理由。
+
+```typescript
+let a:Symbol = Object(Symbol());
+let b:BigInt = Object(BigInt());
+```
+
+上面示例中,得到的就是 Symbol 和 BigInt 的包装对象,但是没有使用的意义。
 
 ## Object 类型与 object 类型
 

From b017512f257cb33b05eb16622a3b646f5acd8c8b Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 14 Aug 2023 12:12:46 +0800
Subject: [PATCH 012/120] docs(function): fixed typo

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index c489540..62e7c23 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -887,7 +887,7 @@ JavaScript 语言使用构造函数,生成对象的实例。
 const d = new Date();
 ```
 
-上面示例中,`date()`就是一个构造函数,使用`new`命令调用,返回 Date 对象的实例。
+上面示例中,`Date()`就是一个构造函数,使用`new`命令调用,返回 Date 对象的实例。
 
 构造函数的类型写法,就是在参数列表前面加上`new`命令。
 

From 8a1ae219edd0f2cb01a366440669fa7a07edfe94 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 14 Aug 2023 12:17:01 +0800
Subject: [PATCH 013/120] docs(module): fixed #31 typo

---
 docs/module.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/module.md b/docs/module.md
index 329c6e4..91e98fd 100644
--- a/docs/module.md
+++ b/docs/module.md
@@ -54,7 +54,7 @@ $ tsc a.ts b.ts
 $ tsc b.ts
 ```
 
-上面命令发现`b.ts`依赖`a.js`,就会自动寻找`a.ts`,也将其同时编译,因此编译产物还是`a.js`和`b.js`两个文件。
+上面命令发现`b.ts`依赖`a.ts`,就会自动寻找`a.ts`,也将其同时编译,因此编译产物还是`a.js`和`b.js`两个文件。
 
 如果想将`a.ts`和`b.ts`编译成一个文件,可以使用`--outFile`参数。
 

From fb36e1767e3db6014e4371052eda5c20b2ec74f6 Mon Sep 17 00:00:00 2001
From: EthanLiu2023 <liuwenhua@ata.net.cn>
Date: Mon, 14 Aug 2023 14:01:49 +0800
Subject: [PATCH 014/120] =?UTF-8?q?=E5=8B=98=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/namespace.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/namespace.md b/docs/namespace.md
index 3179095..c5dce93 100644
--- a/docs/namespace.md
+++ b/docs/namespace.md
@@ -266,7 +266,7 @@ C.bar // 2
 
 上面示例中,名称空间`C`为类`C`添加了一个静态属性`bar`。
 
-命名空间还能于同名 Enum 合并。
+命名空间还能与同名 Enum 合并。
 
 ```typescript
 enum E {

From e89c53427c50e0d78ace935ff87932f3cdabdd80 Mon Sep 17 00:00:00 2001
From: EthanLiu2023 <liuwenhua@ata.net.cn>
Date: Mon, 14 Aug 2023 14:51:53 +0800
Subject: [PATCH 015/120] =?UTF-8?q?fix:=E7=AC=AC19=E7=AB=A0=E6=96=87?=
 =?UTF-8?q?=E5=AD=97=E5=8B=98=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/declare.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/declare.md b/docs/declare.md
index 192f3e1..918c44f 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -215,7 +215,7 @@ declare module 'moduleA' {
 
 上面示例中,从模块`moduleA`导入了`Foo`接口,将其重命名为`Bar`,并用 declare 关键字为`Bar`增加一个属性`custom`。
 
-下面是另一个例子。一个项目有多个模块,可以在一个模型中,对另一个模块的接口进行类型扩展。
+下面是另一个例子。一个项目有多个模块,可以在一个模块中,对另一个模块的接口进行类型扩展。
 
 ```typescript
 // a.ts

From 7655c27e382cc77fb22114a7eca30e106db34b8e Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Mon, 14 Aug 2023 15:02:48 +0800
Subject: [PATCH 016/120] fix: typo

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index 62e7c23..48f456f 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -774,7 +774,7 @@ function add(
 
 上面示例中,函数`add()`内部使用`if`代码块,分别处理参数的两种情况。
 
-注意,重载的个别类型描述与函数的具体实现之间,不能有其他代码,否则报错。
+注意,重载的各个类型描述与函数的具体实现之间,不能有其他代码,否则报错。
 
 另外,虽然函数的具体实现里面,有完整的类型声明。但是,函数实际调用的类型,以前面的类型声明为准。比如,上例的函数实现,参数类型和返回值类型都是`number|any[]`,但不意味着参数类型为`number`时返回值类型为`any[]`。
 

From dbacc81e668133256d0d59ef70830e17cfa6c25a Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 00:28:15 +0800
Subject: [PATCH 017/120] docs(class): fix typo

---
 docs/class.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/class.md b/docs/class.md
index b7db13b..ca70395 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -471,7 +471,7 @@ class SecretCar implements SuperCar {
 }
 ```
 
-上面示例中,接口`SuperCar`通过`SuperCar`接口,就间接实现了多个接口。
+上面示例中,类`SecretCar`通过`SuperCar`接口,就间接实现了多个接口。
 
 注意,发生多重实现时(即一个接口同时实现多个接口),不同接口不能有互相冲突的属性。
 

From b27f84bf94aa5063dbcfc3f8ab0d5cfc8fd9f4b4 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 00:30:27 +0800
Subject: [PATCH 018/120] docs(enum): fix typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index f4cff92..2f3d851 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -404,7 +404,7 @@ enum Foo {
 }
 ```
 
-上面示例中,`A`之前没有其他成员,所以可以不设置初始值,默认等于`0`;`C`之前有一个字符串成员,必须`C`必须有初始值,不赋值就报错了。
+上面示例中,`A`之前没有其他成员,所以可以不设置初始值,默认等于`0`;`C`之前有一个字符串成员,所以`C`必须有初始值,不赋值就报错了。
 
 Enum 成员可以是字符串和数值混合赋值。
 

From d50c9ade072cd3b420c53b7355d03a8994a4aafa Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 08:38:12 +0800
Subject: [PATCH 019/120] docs(object): fixed #35 optional property

---
 docs/object.md | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/docs/object.md b/docs/object.md
index 518c137..eebeef2 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -167,13 +167,22 @@ type User = {
 // 等同于
 type User = {
   firstName: string;
-  lastName: string|undefined;
+  lastName?: string|undefined;
 };
 ```
 
-上面示例中,类型`User`的属性`lastName`可以是字符串,也可以是`undefined`,就表示该属性可以省略不写。
+上面示例中,类型`User`的可选属性`lastName`可以是字符串,也可以是`undefined`,即可选属性可以赋值为`undefined`。
 
-同理,读取一个可选属性时,有可能返回`undefined`。
+```typescript
+const obj: {
+  x: number;
+  y?: number;
+} = { x: 1, y: undefined };
+```
+
+上面示例中,可选属性`y`赋值为`undefined`,不会报错。
+
+同样地,读取一个没有赋值的可选属性时,返回`undefined`。
 
 ```typescript
 type MyObj = {
@@ -185,7 +194,7 @@ const obj:MyObj = { x: 'hello' };
 obj.y.toLowerCase() // 报错
 ```
 
-上面示例中,最后一行会报错,因为`obj.y`有可能是`undefined`,无法对其调用`toLowerCase()`。
+上面示例中,最后一行会报错,因为`obj.y`返回`undefined`,无法对其调用`toLowerCase()`。
 
 所以,读取可选属性之前,必须检查一下是否为`undefined`。
 
@@ -216,6 +225,30 @@ let lastName = user.lastName ?? 'Bar';
 
 上面示例中,写法一使用三元运算符`?:`,判断是否为`undefined`,并设置默认值。写法二使用 Null 判断运算符`??`,与写法一的作用完全相同。
 
+TypeScript 提供编译设置`ExactOptionalPropertyTypes`,只要同时打开这个设置和`strictNullChecks`,可选属性就不能设为`undefined`。
+
+```typescript
+// 打开 ExactOptionsPropertyTypes 和 strictNullChecks
+const obj: {
+  x: number;
+  y?: number;
+} = { x: 1, y: undefined }; // 报错
+```
+
+上面示例中,打开了这两个设置以后,可选属性就不能设为`undefined`了。
+
+注意,可选属性与允许设为`undefined`的必选属性是不等价的。
+
+```typescript
+type A = { x:number, y?:number };
+type B = { x:number, y:number|undefined };
+
+const ObjA:A = { x: 1 }; // 正确
+const ObjB:B = { x: 1 }; // 报错
+```
+
+上面示例中,属性`y`如果是一个可选属性,那就可以省略不写;如果是允许设为`undefined`的必选属性,一旦省略就会报错,必须显式写成`{ x: 1, y: undefined }`。
+
 ## 只读属性
 
 属性名前面加上`readonly`关键字,表示这个属性是只读属性,不能修改。

From 3459a161ae3a173a333f1dabeebd26599fabad1e Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 08:54:05 +0800
Subject: [PATCH 020/120] docs(class): edit property initial value

---
 docs/class.md | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index ca70395..a54682a 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -41,14 +41,22 @@ class Point {
 
 上面示例中,属性`x`和`y`的类型都会被推断为 number。
 
-TypeScript 有一个配置项`strictPropertyInitialization`,只要打开,就会检查属性是否设置了初值,如果没有就报错。
+TypeScript 有一个配置项`strictPropertyInitialization`,只要打开(默认是打开的),就会检查属性是否设置了初值,如果没有就报错。
 
-如果你打开了这个设置,但是某些情况下,不是在声明时赋值或在构造方法里面赋值,为了防止这个设置报错,可以使用非空断言。
+```typescript
+// 打开 strictPropertyInitialization
+class Point {
+  x: number; // 报错
+  y: number; // 报错
+}
+```
+
+上面示例中,如果类的顶层属性不赋值,就会报错。如果不希望出现报错,可以使用非空断言。
 
 ```typescript
 class Point {
-  x!:number;
-  y!:number;
+  x!: number;
+  y!: number;
 }
 ```
 

From 33d0b9e1d4ac785499fb98e550a368d8c0e3e305 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 08:59:48 +0800
Subject: [PATCH 021/120] docs(class): fixed #36 ES6 -> ES2022

---
 docs/class.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index a54682a..34e0413 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -1091,7 +1091,7 @@ if ('x' in a) { // 正确
 
 上面示例中,`A`类的属性`x`是私有属性,但是实例使用方括号,就可以读取这个属性,或者使用`in`运算符检查这个属性是否存在,都可以正确执行。
 
-由于`private`存在这些问题,加上它是 ES6 标准发布前出台的,而 ES6 引入了自己的私有成员写法`#propName`。因此建议不使用`private`,改用 ES6 的写法,获得真正意义的私有成员。
+由于`private`存在这些问题,加上它是 ES2022 标准发布前出台的,而 ES2022 引入了自己的私有成员写法`#propName`。因此建议不使用`private`,改用 ES2022 的写法,获得真正意义的私有成员。
 
 ```typescript
 class A {
@@ -1102,7 +1102,7 @@ const a = new A();
 a['x'] // 报错
 ```
 
-上面示例中,采用了 ES6 的私有成员写法(属性名前加`#`),TypeScript 就正确识别了实例对象没有属性`x`,从而报错。
+上面示例中,采用了 ES2022 的私有成员写法(属性名前加`#`),TypeScript 就正确识别了实例对象没有属性`x`,从而报错。
 
 构造方法也可以是私有的,这就直接防止了使用`new`命令生成实例对象,只能在类的内部创建实例对象。
 

From 062f30ce829871aa466db6dfe2af471aafc75ed0 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 09:19:44 +0800
Subject: [PATCH 022/120] docs(declare): adjuest txt

---
 docs/declare.md | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/docs/declare.md b/docs/declare.md
index 918c44f..f1eb9b9 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -100,7 +100,7 @@ function sayHello(name) {
 
 ## declare class
 
-declare 给出 class 的描述描述写法如下。
+declare 给出 class 类型描述的写法如下。
 
 ```typescript
 declare class Animal {
@@ -176,7 +176,7 @@ declare namespace Foo {
 }
 
 declare module 'io' {
- export function readFile(filename:string):string;
+  export function readFile(filename:string):string;
 }
 ```
 
@@ -187,6 +187,7 @@ declare module 'io' {
 ```typescript
 let result = myLib.makeGreeting('你好');
 console.log('欢迎词:' + result);
+
 let count = myLib.numberOfGreetings;
 ```
 
@@ -194,8 +195,8 @@ let count = myLib.numberOfGreetings;
 
 ```typescript
 declare namespace myLib {
-  function makeGreeting(s:string):string;
-  let numberOfGreetings:number;
+  function makeGreeting(s:string): string;
+  let numberOfGreetings: number;
 }
 ```
 
@@ -207,7 +208,7 @@ import { Foo as Bar } from 'moduleA';
 declare module 'moduleA' {
   interface Bar extends Foo {
     custom: {
-      prop1:string;
+      prop1: string;
     }
   }
 }
@@ -254,7 +255,7 @@ declare module "模块名";
 declare module "hot-new-module";
 ```
 
-加上上面的命令以后,外部模块即使没有类型,也可以通过编译。但是,从该模块输入的所有接口都将为`any`类型。
+加上上面的命令以后,外部模块即使没有类型声明,也可以通过编译。但是,从该模块输入的所有接口都将为`any`类型。
 
 declare module 描述的模块名可以使用通配符。
 

From 28ab32251ec4167df882d0c6cf218e71c24d363d Mon Sep 17 00:00:00 2001
From: Daniel <60702016+leinad59@users.noreply.github.com>
Date: Tue, 15 Aug 2023 10:48:05 +0800
Subject: [PATCH 023/120] docs(object): fix typo

---
 docs/object.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/object.md b/docs/object.md
index eebeef2..6f2518a 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -501,7 +501,7 @@ function draw({
 
 ## 结构类型原则
 
-只要对象 B 满足 对象 A 的结构特征,TypeScript 就认为对象 B 兼容对象 A 的类型,这称为“结构类型”原则(structual typing)。
+只要对象 B 满足 对象 A 的结构特征,TypeScript 就认为对象 B 兼容对象 A 的类型,这称为“结构类型”原则(structural typing)。
 
 ```typescript
 const A = {

From f87ed35e4f42eec5858db93067355dcfaf433661 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 14:18:11 +0800
Subject: [PATCH 024/120] docs(object): fixed #37 minimum optional property
 rule

---
 docs/object.md | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/docs/object.md b/docs/object.md
index eebeef2..27c7768 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -683,7 +683,7 @@ computeDistance({x: 1, y: 2}); // 正确
 
 ## 最小可选属性规则
 
-如果一个对象的所有属性都是可选的,会触发最小可选属性规则。
+根据“结构类型”原则,如果一个对象的所有属性都是可选的,那么其他对象跟它都是结构类似的。
 
 ```typescript
 type Options = {
@@ -691,25 +691,29 @@ type Options = {
   b?:number;
   c?:number;
 };
-
-const obj:Options = {
-  d: 123 // 报错
-};
 ```
 
-上面示例中,类型`Options`是一个对象,它的所有属性都是可选的,这导致任何对象实际都符合`Options`类型。
-
-为了避免这种情况,TypeScript 添加了最小可选属性规则,规定这时属于`Options`类型的对象,必须至少存在一个可选属性,不能所有可选属性都不存在。这就是为什么上例的`myObj`对象会报错的原因。
+上面示例中,类型`Options`的所有属性都是可选的,所以它可以是一个空对象,也就意味着任意对象都满足`Options`的结构。
 
-这条规则无法通过中间变量规避。
+为了避免这种情况,TypeScript 2.4 引入了一个“最小可选属性规则”,也称为[“弱类型检测”](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html#weak-type-detection)(weak type detection)。
 
 ```typescript
-const myOptions = { d: 123 };
+type Options = {
+  a?:number;
+  b?:number;
+  c?:number;
+};
+
+const opts = { d: 123 };
 
-const obj:Options = myOptions; // 报错
+const obj:Options = opts; // 报错
 ```
 
-上面示例中,即使使用了中间变量`myOptions`,由于存在最小可选属性规则,依然会报错。
+上面示例中,对象`opts`与类型`Options`没有共同属性,赋值给该类型的变量就会报错。
+
+报错原因是,如果某个类型的所有属性都是可选的,那么该类型的对象必须至少存在一个可选属性,不能所有可选属性都不存在。这就叫做“最小可选属性规则”。
+
+如果想规避这条规则,要么在类型里面增加一条索性属性(`[propName: string]: someType`),要么使用类型断言(`opts as Options`)。
 
 ## 空对象
 

From 6d7a259be3a698ceb4ea20a17721c68fc21d90fd Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 14:30:05 +0800
Subject: [PATCH 025/120] docs(class): fixed typo

---
 docs/class.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/class.md b/docs/class.md
index 34e0413..71e5a79 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -241,7 +241,7 @@ class C {
 }
 ```
 
-上面示例中,`set`方法的参数类型(`number|return`)兼容`get`方法的返回值类型(`string`),这是允许的。但是,最终赋值的时候,还是必须保证与`get`方法的返回值类型一致。
+上面示例中,`set`方法的参数类型(`number|string`)兼容`get`方法的返回值类型(`string`),这是允许的。但是,最终赋值的时候,还是必须保证与`get`方法的返回值类型一致。
 
 另外,如果`set`方法的参数没有指定类型,那么会推断为与`get`方法返回值类型一致。
 

From 055b15f112af9efabadcb814b2077facbea23c73 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Tue, 15 Aug 2023 14:40:40 +0800
Subject: [PATCH 026/120] fix: typo

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index a1b7c7f..4403922 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -465,7 +465,7 @@ interface A {
 }
 ```
 
-上面示例中,`f()`方法有一个类型声明是,参数`x`是字面量类型,这个类型声明的优先级最高,会排在函数重载的最前面。
+上面示例中,`f()`方法有一个类型声明的参数`x`是字面量类型,这个类型声明的优先级最高,会排在函数重载的最前面。
 
 一个实际的例子是 Document 对象的`createElement()`方法,它会根据参数的不同,而生成不同的 HTML 节点对象。
 

From a20760e7e5c44705dc56e4d934b6d657c21b9b3e Mon Sep 17 00:00:00 2001
From: yuexing <yuexingphp@163.com>
Date: Tue, 15 Aug 2023 14:52:38 +0800
Subject: [PATCH 027/120] =?UTF-8?q?docs(assert):=20=F0=9F=93=83=20fix=20de?=
 =?UTF-8?q?scription?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/assert.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/assert.md b/docs/assert.md
index 48e6f1e..1f982dd 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -429,7 +429,7 @@ const aValue:string|number = 'Hello';
 isString(aValue);
 ```
 
-上面示例中,变量`aValue`可能是字符串,也可能是数组。但是,通过调用`isString()`,后面的代码就可以确定,变量`aValue`一定是字符串。
+上面示例中,变量`aValue`可能是字符串,也可能是数字。但是,通过调用`isString()`,后面的代码就可以确定,变量`aValue`一定是字符串。
 
 断言函数的类型可以写成下面这样。
 

From 9faa8ba76d1b42df11872b5e867987377a87763b Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Tue, 15 Aug 2023 14:57:33 +0800
Subject: [PATCH 028/120] fix: typo

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index 4403922..cf2943f 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -655,7 +655,7 @@ type Foo = {
 ```typescript
 class Calculator implements Foo {
   result = 0;
-  add(num:number) {
+  add(num:number) {
     this.result += num;
     return this;
   }

From 52847444d49fea64dd6b7e2c930f9eabd34a9732 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 16:58:16 +0800
Subject: [PATCH 029/120] docs(class): fixed #38 unrelated types for getters
 and setters

---
 docs/class.md | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index 71e5a79..db81152 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -213,21 +213,22 @@ c.name = 'bar'; // 报错
 
 上面示例中,`name`属性没有`set`方法,对该属性赋值就会报错。
 
-(2)`set`方法的参数类型,必须兼容`get`方法的返回值类型,否则报错。
+(2)TypeScript 5.1 版之前,`set`方法的参数类型,必须兼容`get`方法的返回值类型,否则报错。
 
 ```typescript
+// TypeScript 5.1 版之前
 class C {
   _name = '';
-  get name():string {
+  get name():string {  // 报错
     return this._name;
   }
   set name(value:number) {
-    this._name = value; // 报错
+    this._name = String(value);
   }
 }
 ```
 
-上面示例中,`get`方法的返回值类型是字符串,与`set`方法参数类型不兼容,导致报错。
+上面示例中,`get`方法的返回值类型是字符串,与`set`方法的参数类型`number`不兼容,导致报错。改成下面这样,就不会报错。
 
 ```typescript
 class C {
@@ -236,14 +237,14 @@ class C {
     return this._name;
   }
   set name(value:number|string) {
-    this._name = String(value); // 正确
+    this._name = String(value);
   }
 }
 ```
 
-上面示例中,`set`方法的参数类型(`number|string`)兼容`get`方法的返回值类型(`string`),这是允许的。但是,最终赋值的时候,还是必须保证与`get`方法的返回值类型一致。
+上面示例中,`set`方法的参数类型(`number|string`)兼容`get`方法的返回值类型(`string`),这是允许的。
 
-另外,如果`set`方法的参数没有指定类型,那么会推断为与`get`方法返回值类型一致。
+TypeScript 5.1 版做出了[改变](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html#unrelated-types-for-getters-and-setters),现在两者可以不兼容。
 
 (3)`get`方法与`set`方法的可访问性必须一致,要么都为公开方法,要么都为私有方法。
 

From b147a95bb4c6daaed92f29c2cf339d3097caed84 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 17:37:00 +0800
Subject: [PATCH 030/120] docs(comment): fixed #41 @ts-expect-error

---
 docs/comment.md | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/docs/comment.md b/docs/comment.md
index 2955f77..2869b5a 100644
--- a/docs/comment.md
+++ b/docs/comment.md
@@ -31,19 +31,48 @@ console.log(isChceked); // 报错
 
 ## `// @ts-ignore`
 
-`// @ts-ignore`或`// @ts-expect-error`,告诉编译器不对下一行代码进行类型检查,可以用于 TypeScript 脚本,也可以用于 JavaScript 脚本。
+`// @ts-ignore`告诉编译器不对下一行代码进行类型检查,可以用于 TypeScript 脚本,也可以用于 JavaScript 脚本。
 
 ```typescript
 let x:number;
 
 x = 0;
 
-// @ts-expect-error
+// @ts-ignore
 x = false; // 不报错
 ```
 
 上面示例中,最后一行是类型错误,变量`x`的类型是`number`,不能等于布尔值。但是因为前面加上了`// @ts-expect-error`,编译器会跳过这一行的类型检查,所以不会报错。
 
+## `// @ts-expect-error`
+
+`// @ts-expect-error`主要用在测试用例,当下一行有类型错误时,它会压制 TypeScript 的报错信息(即不显示报错信息),把错误留给代码自己处理。
+
+```typescript
+function doStuff(abc: string, xyz: string) {
+  assert(typeof abc === "string");
+  assert(typeof xyz === "string");
+  // do some stuff
+}
+
+// @ts-expect-error
+expect(() => {
+  doStuff(123, 456);
+}).toThrow();
+```
+
+上面示例是一个测试用例,倒数第二行的`doStuff(123, 456)`的参数类型与定义不一致,TypeScript 引擎会报错。但是,测试用例本身测试的就是这个错误,已经有专门的处理代码,所以这里可以使用`// @ts-expect-error`,不显示引擎的报错信息。
+
+如果下一行没有类型错误,`// @ts-expect-error`则会显示一行提示。
+
+```typescript
+// @ts-expect-error
+console.log(1 + 1);
+// 输出 Unused '@ts-expect-error' directive.
+```
+
+上面示例中,第二行是正确代码,这时系统会给出一个提示,表示`@ts-expect-error`没有用到。
+
 ## JSDoc
 
 TypeScript 直接处理 JS 文件时,如果无法推断出类型,会使用 JS 脚本里面的 JSDoc 注释。

From a654be9a9976ed07ae89c71444b53bcfaf5cef48 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 17:40:31 +0800
Subject: [PATCH 031/120] docs(assert): fix typo

---
 docs/assert.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/assert.md b/docs/assert.md
index 1f982dd..38ca257 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -429,7 +429,7 @@ const aValue:string|number = 'Hello';
 isString(aValue);
 ```
 
-上面示例中,变量`aValue`可能是字符串,也可能是数字。但是,通过调用`isString()`,后面的代码就可以确定,变量`aValue`一定是字符串。
+上面示例中,变量`aValue`可能是字符串,也可能是数值。但是,通过调用`isString()`,后面的代码就可以确定,变量`aValue`一定是字符串。
 
 断言函数的类型可以写成下面这样。
 

From 652dbb35786d597f621de90da67209f3b453d936 Mon Sep 17 00:00:00 2001
From: chentong <chentong19950106@gmail.com>
Date: Tue, 15 Aug 2023 18:10:05 +0800
Subject: [PATCH 032/120] update text

---
 docs/object.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/object.md b/docs/object.md
index d6021d6..6502bfa 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -336,7 +336,7 @@ w.age += 1;
 r.age // 43
 ```
 
-上面示例中,变量`w`和`r`指向同一个对象,其中`w`是可写的,`r`的只读的。那么,对`w`的属性修改,会影响到`r`。
+上面示例中,变量`w`和`r`指向同一个对象,其中`w`是可写的,`r`是只读的。那么,对`w`的属性修改,会影响到`r`。
 
 如果希望属性值是只读的,除了声明时加上`readonly`关键字,还有一种方法,就是在赋值时,在对象后面加上只读断言`as const`。
 

From a529d6c123ca934390b05500811a8c93de592ed8 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 20:13:38 +0800
Subject: [PATCH 033/120] docs(decorator): edit text

---
 docs/decorator.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/decorator.md b/docs/decorator.md
index 70ea454..c8d0805 100644
--- a/docs/decorator.md
+++ b/docs/decorator.md
@@ -41,15 +41,15 @@ class A {} // "hi"
 
 ```typescript
 function simpleDecorator(
-  target:any,
+  value:any,
   context:any
 ) {
-  console.log('hi, this is ' + target);
-  return target;
+  console.log(`hi, this is ${context.kind} ${context.name}`);
+  return value;
 }
 
 @simpleDecorator
-class A {} // "hi, this is class A {}" 
+class A {} // "hi, this is class A"
 ```
 
 上面的代码就可以顺利通过编译了,代码含义这里先不解释。大家只要理解,类`A`在执行前会先执行装饰器`simpleDecorator()`,并且会向装饰器自动传入参数就可以了。

From 39891fe0abaa32955a419cdca286c85abc906142 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Aug 2023 20:15:55 +0800
Subject: [PATCH 034/120] docs(enum): fix typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index 2f3d851..cb2ebd1 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -372,7 +372,7 @@ const enum E {
 enum E {
   A,
 }
-const enum E2 {
+const enum E {
   B = 1,
 }
 ```

From 96f4e0093106b9c51133bee6d2d3e805928af3d7 Mon Sep 17 00:00:00 2001
From: owen123f <owen@anasystem.com.tw>
Date: Wed, 16 Aug 2023 07:54:11 +0800
Subject: [PATCH 035/120] fix: typo in comment.md

---
 docs/comment.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/comment.md b/docs/comment.md
index 2869b5a..38ddfa7 100644
--- a/docs/comment.md
+++ b/docs/comment.md
@@ -42,7 +42,7 @@ x = 0;
 x = false; // 不报错
 ```
 
-上面示例中,最后一行是类型错误,变量`x`的类型是`number`,不能等于布尔值。但是因为前面加上了`// @ts-expect-error`,编译器会跳过这一行的类型检查,所以不会报错。
+上面示例中,最后一行是类型错误,变量`x`的类型是`number`,不能等于布尔值。但是因为前面加上了`// @ts-ignore`,编译器会跳过这一行的类型检查,所以不会报错。
 
 ## `// @ts-expect-error`
 

From 1c27107fe71829e17bd59cc0e8aee7cacbfb73eb Mon Sep 17 00:00:00 2001
From: chentong <chentong19950106@gmail.com>
Date: Wed, 16 Aug 2023 10:29:07 +0800
Subject: [PATCH 036/120] update text

---
 docs/object.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/object.md b/docs/object.md
index 6502bfa..cc37590 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -610,7 +610,7 @@ type Options = {
   darkMode?:boolean;
 };
 
-const Obj:Options = {
+const obj:Options = {
   title: '我的网页',
   darkmode: true, // 报错
 };
@@ -626,7 +626,7 @@ let myOptions = {
   darkmode: true,
 };
 
-const Obj:Options = myOptions;
+const obj:Options = myOptions;
 ```
 
 上面示例中,创建了一个中间变量`myOptions`,就不会触发严格字面量规则,因为这时变量`obj`的赋值,不属于直接字面量赋值。
@@ -634,7 +634,7 @@ const Obj:Options = myOptions;
 如果你确认字面量没有错误,也可以使用类型断言规避严格字面量检查。
 
 ```typescript
-const Obj:Options = {
+const obj:Options = {
   title: '我的网页',
   darkmode: true,
 } as Options;

From c8a81d47e55885ed27ccbfeb79d990ee24612777 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Wed, 16 Aug 2023 14:00:37 +0800
Subject: [PATCH 037/120] fix: typo

---
 docs/class.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/class.md b/docs/class.md
index db81152..9d5f052 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -1351,7 +1351,7 @@ class Box<Type> {
 
 ## 抽象类,抽象成员
 
-TypeScript 允许在类的定义前面,加上关键字`abstract`,表示该类不能被实例化,只能当作其他类的模板。这种类就叫做“抽象类”(abastract class)。
+TypeScript 允许在类的定义前面,加上关键字`abstract`,表示该类不能被实例化,只能当作其他类的模板。这种类就叫做“抽象类”(abstract class)。
 
 ```typescript
 abstract class A {

From 06e925ceb6901f4a5af4d2ac8347d6d2f3ba007e Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 16 Aug 2023 16:46:47 +0800
Subject: [PATCH 038/120] docs(assert): modify assertion function

---
 docs/assert.md | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/docs/assert.md b/docs/assert.md
index 38ca257..4163279 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -414,33 +414,26 @@ class Point {
 断言函数是一种特殊函数,用于保证函数参数符合某种类型。如果函数参数达不到要求,就会抛出错误,中断程序执行;如果达到要求,就不进行任何操作,让代码按照正常流程运行。
 
 ```typescript
-function isString(value) {
+function isString(value:unknown):void {
   if (typeof value !== 'string')
     throw new Error('Not a string');
 }
 ```
 
-上面示例中,函数`isString()`就是一个断言函数,用来保证参数`value`是一个字符串。
+上面示例中,函数`isString()`就是一个断言函数,用来保证参数`value`是一个字符串,否则就会抛出错误,中断程序的执行。
 
 下面是它的用法。
 
 ```typescript
-const aValue:string|number = 'Hello';
-isString(aValue);
-```
-
-上面示例中,变量`aValue`可能是字符串,也可能是数值。但是,通过调用`isString()`,后面的代码就可以确定,变量`aValue`一定是字符串。
-
-断言函数的类型可以写成下面这样。
-
-```typescript
-function isString(value:unknown):void {
-  if (typeof value !== 'string')
-    throw new Error('Not a string');
+function toUpper(x: string|number) {
+  isString(x);
+  return x.toUpperCase();
 }
 ```
 
-上面代码中,函数参数`value`的类型是`unknown`,返回值类型是`void`,即没有返回值。可以看到,单单从这样的类型声明,很难看出`isString()`是一个断言函数。
+上面示例中,函数`toUpper()`的参数`x`,可能是字符串,也可能是数值。但是,函数体的最后一行调用`toUpperCase()`方法,必须保证`x`是字符串,否则报错。所以,这一行前面调用断言函数`isString()`,调用以后 TypeScript 就能确定,变量`x`一定是字符串,不是数值,也就不报错了。
+
+传统的断言函数`isString()`的写法有一个缺点,它的参数类型是`unknown`,返回值类型是`void`(即没有返回值)。单单从这样的类型声明,很难看出`isString()`是一个断言函数。
 
 为了更清晰地表达断言函数,TypeScript 3.7 引入了新的类型写法。
 

From d75e8a9765ffd9169d76586e00df75b4e46cd5de Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 16 Aug 2023 16:48:50 +0800
Subject: [PATCH 039/120] docs(tsconfig.json): fix typo

---
 docs/tsconfig.json.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index e0896bd..3f48c12 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -386,7 +386,7 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 - ES2020
 - ES2021
 - ES2022
-- ESNex
+- ESNext
 - DOM
 - WebWorker
 - ScriptHost

From 8c0ed20b7a71623d3d7c529792ef3560da6e4c5d Mon Sep 17 00:00:00 2001
From: lean <efilehtyojne@qq.com>
Date: Thu, 17 Aug 2023 12:19:42 +0800
Subject: [PATCH 040/120] docs: fix typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index cb2ebd1..c1d471a 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -452,7 +452,7 @@ f('One') // 报错
 
 所以,字符串 Enum 作为一种类型,有限定函数参数的作用。
 
-前面说过,数值 Enum 的成员值往往不重要。但是有些场合,开发者可能希望 Enum 成员值可以保存一些有用的信息,所以 TypeScript 才设计了字符串 Enum.
+前面说过,数值 Enum 的成员值往往不重要。但是有些场合,开发者可能希望 Enum 成员值可以保存一些有用的信息,所以 TypeScript 才设计了字符串 Enum。
 
 ```typescript
 const enum MediaTypes {

From d22f1bb9ecbe293e36c920644e66fd9259d6a34d Mon Sep 17 00:00:00 2001
From: liuchao <liuchao_huoguo@163.com>
Date: Thu, 17 Aug 2023 14:02:39 +0800
Subject: [PATCH 041/120] docs: fix typo

---
 docs/decorator-legacy.md | 4 ++--
 docs/tsc.md              | 2 +-
 docs/types.md            | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/decorator-legacy.md b/docs/decorator-legacy.md
index dad1137..b1cc1d3 100644
--- a/docs/decorator-legacy.md
+++ b/docs/decorator-legacy.md
@@ -588,7 +588,7 @@ class C {
     @log x:number,
     @log y:number
   ) {
-    console.log(`member Paremeters: ${x} ${y}`);
+    console.log(`member Parameters: ${x} ${y}`);
   }
 }
 
@@ -596,7 +596,7 @@ const c = new C();
 c.member(5, 5);
 // member NO.1 Parameter
 // member NO.0 Parameter 
-// member Paremeters: 5 5 
+// member Parameters: 5 5 
 ```
 
 上面示例中,参数装饰器会输出参数的位置序号。注意,后面的参数会先输出。
diff --git a/docs/tsc.md b/docs/tsc.md
index f2beddf..16bb89d 100644
--- a/docs/tsc.md
+++ b/docs/tsc.md
@@ -172,7 +172,7 @@ tsc 的命令行参数,大部分与 tsconfig.json 的属性一一对应。
 
 `--suppressExcessPropertyErrors`:关闭对象字面量的多余参数的报错。
 
-`--target`:指定编译出来的 JS 代码的版本,TypeScirpt 还会在编译时自动加入对应的库类型声明文件。
+`--target`:指定编译出来的 JS 代码的版本,TypeScript 还会在编译时自动加入对应的库类型声明文件。
 
 `--traceResolution`:编译时在终端输出模块解析(moduleResolution)的具体步骤。
 
diff --git a/docs/types.md b/docs/types.md
index c7a618f..dab6564 100644
--- a/docs/types.md
+++ b/docs/types.md
@@ -390,7 +390,7 @@ let x:undefined = null; // 报错
 let y:null = undefined; // 报错
 ```
 
-上面示例中,`undefined`类型的变量赋值为`null`,或者`null`类型的变量赋值为`undefind`,都会报错。
+上面示例中,`undefined`类型的变量赋值为`null`,或者`null`类型的变量赋值为`undefined`,都会报错。
 
 总之,打开`strictNullChecks`以后,`undefined`和`null`只能赋值给自身,或者`any`类型和`unknown`类型的变量。
 

From 59e0b3b85bb03508bc20339f63e4c4ceeaffa170 Mon Sep 17 00:00:00 2001
From: lean <efilehtyojne@qq.com>
Date: Thu, 17 Aug 2023 18:38:12 +0800
Subject: [PATCH 042/120] docs: fix unexpected newline and space
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

出现了意外的换行和空格
---
 docs/assert.md | 3 +--
 docs/module.md | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/docs/assert.md b/docs/assert.md
index 4163279..5c6659c 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -228,8 +228,7 @@ let s = 'JavaScript';
 setLang(s as const); // 报错
 ```
 
-上面示例中,`as
-const`断言用于变量`s`,就报错了。下面的写法可以更清晰地看出这一点。
+上面示例中,`as const`断言用于变量`s`,就报错了。下面的写法可以更清晰地看出这一点。
 
 ```typescript
 let s1 = 'JavaScript';
diff --git a/docs/module.md b/docs/module.md
index 91e98fd..ea6cc32 100644
--- a/docs/module.md
+++ b/docs/module.md
@@ -221,7 +221,7 @@ let obj = { foo: 123 };
 export = obj;
 ```
 
-`export = `语句输出的对象,只能使用`import =`语句加载。
+`export =`语句输出的对象,只能使用`import =`语句加载。
 
 ```typescript
 import obj = require('./a');

From ed8175f631b16891628aefe2f8a4ab89a16277d4 Mon Sep 17 00:00:00 2001
From: gaufung <gaufung@outlook.com>
Date: Fri, 18 Aug 2023 08:05:37 +0800
Subject: [PATCH 043/120] change .Net to .NET

---
 docs/intro.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/intro.md b/docs/intro.md
index bb965c6..9771caf 100644
--- a/docs/intro.md
+++ b/docs/intro.md
@@ -175,7 +175,7 @@ TypeScript 依赖 JavaScript 生态,需要用到很多外部模块。但是,
 
 当时,Windows 8 即将发布,它的应用程序开发除了使用 C# 和 Visual Basic,还可以使用 HTML + JavaScript。微软希望,TypeScript 既能让 JavaScript 程序员快速上手,也能让 .Net 程序员感到熟悉。
 
-这就是说,TypeScript 的最初动机是减少 .Net 程序员的转移和学习成本。所以,它的很多语法概念跟 .Net 很类似。
+这就是说,TypeScript 的最初动机是减少 .NET 程序员的转移和学习成本。所以,它的很多语法概念跟 .NET 很类似。
 
 另外,TypeScript 是一个开源项目,接受社区的参与,核心的编译器采用 Apache 2.0 许可证。微软希望通过这种做法,迅速提高这门语言在社区的接受度。
 

From 04d1a723d161bf647eee41836d7d40d4d6f93ae7 Mon Sep 17 00:00:00 2001
From: gaufung <gaufung@outlook.com>
Date: Fri, 18 Aug 2023 08:07:05 +0800
Subject: [PATCH 044/120] fix more .Net

---
 docs/intro.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/intro.md b/docs/intro.md
index 9771caf..75000e0 100644
--- a/docs/intro.md
+++ b/docs/intro.md
@@ -169,7 +169,7 @@ TypeScript 依赖 JavaScript 生态,需要用到很多外部模块。但是,
 
 下面简要介绍 TypeScript 的发展历史。
 
-2012年,微软公司宣布推出 TypeScript 语言,设计者是著名的编程语言设计大师 Anders Hejlsberg,他也是 C# 和 .Net 的设计师。
+2012年,微软公司宣布推出 TypeScript 语言,设计者是著名的编程语言设计大师 Anders Hejlsberg,他也是 C# 和 .NET 的设计师。
 
 微软推出这门语言的主要目的,是让 JavaScript 程序员可以参与 Windows 8 应用程序的开发。
 

From 20effd34b555876047d249a16ba0b5d4a8334d34 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Fri, 18 Aug 2023 09:20:31 +0800
Subject: [PATCH 045/120] fix: typo

---
 docs/generics.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/generics.md b/docs/generics.md
index 4c8ad87..06723a9 100644
--- a/docs/generics.md
+++ b/docs/generics.md
@@ -221,7 +221,7 @@ foo.add = function (x, y) {
 };
 ```
 
-上面示例中,先新建类`C`的实例`foo`,然后再定义示例的`value`属性和`add()`方法。类的定义中,属性和方法后面的感叹号是非空断言,告诉 TypeScript 它们都是非空的,后面会赋值。
+上面示例中,先新建类`C`的实例`foo`,然后再定义实例的`value`属性和`add()`方法。类的定义中,属性和方法后面的感叹号是非空断言,告诉 TypeScript 它们都是非空的,后面会赋值。
 
 JavaScript 的类本质上是一个构造函数,因此也可以把泛型类写成构造函数。
 

From e139724341ad8f5f3d02038b595bb724857fba85 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Fri, 18 Aug 2023 10:05:30 +0800
Subject: [PATCH 046/120] fix: typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index c1d471a..2c795de 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -32,7 +32,7 @@ enum Color {
 }
 ```
 
-上面示例声明了一个 Enum 结构`Color`,里面包含三个成员`Red`、`Green`和`Blue`。第一个成员的值默认为整数`0`,第二个为`1`,第二个为`2`,以此类推。
+上面示例声明了一个 Enum 结构`Color`,里面包含三个成员`Red`、`Green`和`Blue`。第一个成员的值默认为整数`0`,第二个为`1`,第三个为`2`,以此类推。
 
 使用时,调用 Enum 的某个成员,与调用对象属性的写法一样,可以使用点运算符,也可以使用方括号运算符。
 

From 8009d3b347e050ee0cc3950095f33e846fd0e8da Mon Sep 17 00:00:00 2001
From: chentong <chentong19950106@gmail.com>
Date: Fri, 18 Aug 2023 15:45:51 +0800
Subject: [PATCH 047/120] fix:typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index c1d471a..a87414e 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -532,7 +532,7 @@ enum MyEnum {
   B = 'b'
 }
 
-// { a:any, b: any }
+// { a: any, b: any }
 type Foo = { [key in MyEnum]: any };
 ```
 

From 2d904579e33b233f1371cd77d4382a7d49fe67db Mon Sep 17 00:00:00 2001
From: chentong <chentong19950106@gmail.com>
Date: Fri, 18 Aug 2023 15:47:53 +0800
Subject: [PATCH 048/120] fix:typo

---
 docs/operator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index 2f35583..15e096a 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -312,7 +312,7 @@ type T = Obj[string];
 这个语法对于数组也适用,可以使用`number`作为方括号的参数。
 
 ```typescript
-// MyArray 的类型是 { [key:number]:string }
+// MyArray 的类型是 { [key:number]: string }
 const MyArray = ['a','b','c'];
 
 // 等同于 (typeof MyArray)[number]

From 0f7f99d27e38a1b7f80fabce5d737a4079acc545 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 19 Aug 2023 00:46:07 +0800
Subject: [PATCH 049/120] docs(types): fix Symbol/BigInt #56

---
 docs/types.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/types.md b/docs/types.md
index dab6564..e8d63b7 100644
--- a/docs/types.md
+++ b/docs/types.md
@@ -238,12 +238,14 @@ Math.abs(n2) // 报错
 上一小节说过,`Symbol()`和`BigInt()`这两个函数不能当作构造函数使用,所以没有办法直接获得 symbol 类型和 bigint 类型的包装对象,除非使用下面的写法。但是,它们没有使用场景,因此`Symbol`和`BigInt`这两个类型虽然存在,但是完全没有使用的理由。
 
 ```typescript
-let a:Symbol = Object(Symbol());
-let b:BigInt = Object(BigInt());
+let a = Object(Symbol());
+let b = Object(BigInt());
 ```
 
 上面示例中,得到的就是 Symbol 和 BigInt 的包装对象,但是没有使用的意义。
 
+注意,目前在 TypeScript 里面,`symbol`和`Symbol`两种写法没有差异,`bigint`和`BigInt`也是如此,不知道是否属于官方的疏忽。建议始终使用小写的`symbol`和`bigint`,不使用大写的`Symbol`和`BigInt`。
+
 ## Object 类型与 object 类型
 
 TypeScript 的对象类型也有大写`Object`和小写`object`两种。

From 6bea4615cd2525dfd72052defaea3b417e4564e7 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 19 Aug 2023 08:10:21 +0800
Subject: [PATCH 050/120] docs(object): fixed #58

---
 docs/object.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/object.md b/docs/object.md
index cc37590..05d1165 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -504,11 +504,11 @@ function draw({
 只要对象 B 满足 对象 A 的结构特征,TypeScript 就认为对象 B 兼容对象 A 的类型,这称为“结构类型”原则(structural typing)。
 
 ```typescript
-const A = {
+type A = {
   x: number;
 };
 
-const B = {
+type B = {
   x: number;
   y: number;
 };

From cdbbab46f370ad51a4eb70ee4340e1f9e19ee322 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 19 Aug 2023 14:54:05 +0800
Subject: [PATCH 051/120] docs(class): fixed #59

---
 docs/class.md | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index 9d5f052..162a0e0 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -1409,9 +1409,7 @@ class B extends A {
 
 上面示例中,抽象类`A`定义了抽象属性`foo`,子类`B`必须实现这个属性,否则会报错。
 
-下面是抽象方法的例子。
-
-如果抽象类的属性前面加上`abstract`,就表明子类必须给出该方法的实现。
+下面是抽象方法的例子。如果抽象类的方法前面加上`abstract`,就表明子类必须给出该方法的实现。
 
 ```typescript
 abstract class A {

From 77bfab0b4a18cbd25d51297b3e229b8b5f8aabaf Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 19 Aug 2023 15:43:03 +0800
Subject: [PATCH 052/120] docs(types): fixed #55

---
 docs/types.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/types.md b/docs/types.md
index e8d63b7..dac280c 100644
--- a/docs/types.md
+++ b/docs/types.md
@@ -455,7 +455,7 @@ x = y; // 报错
 y = x; // 正确
 ```
 
-上面示例中,变量`x`属于子类型,变量`y`属于父类型。`y`不能赋值为子类型`x`,但是反过来是可以的。
+上面示例中,变量`x`属于子类型,变量`y`属于父类型。子类型`x`不能赋值为父类型`y`,但是反过来是可以的。
 
 如果一定要让子类型可以赋值为父类型的值,就要用到类型断言(详见《类型断言》一章)。
 

From eff43ce88935ea4ce283ce6c7106c84ff791af66 Mon Sep 17 00:00:00 2001
From: Ayaka <26200808+KiritaniAyaka@users.noreply.github.com>
Date: Sat, 19 Aug 2023 20:05:36 +0800
Subject: [PATCH 053/120] docs(class): add extra description for class and
 interface merging

---
 docs/class.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/docs/class.md b/docs/class.md
index 162a0e0..66e5da9 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -498,7 +498,7 @@ interface Swimmable {
 
 ### 类与接口的合并
 
-TypeScript 不允许两个同名的类,但是如果一个类和一个接口同名,那么接口会被合并进类。
+TypeScript 不允许两个同名的类,但是如果一个类和一个接口同名,那么接口会被合并进类。值得注意的是,合并进类的非空属性,在实际使用中可能为空。
 
 ```typescript
 class A {
@@ -510,6 +510,8 @@ interface A {
 }
 
 let a = new A();
+a.y // undefined
+
 a.y = 10;
 
 a.x // 1

From a39a9547166627ead974f1130bbdb05097e394e1 Mon Sep 17 00:00:00 2001
From: biubiubiu999 <houshengaaa@gmail.com>
Date: Sat, 19 Aug 2023 23:58:34 +0800
Subject: [PATCH 054/120] fix:typo

---
 docs/object.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/object.md b/docs/object.md
index 05d1165..8151363 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -713,7 +713,7 @@ const obj:Options = opts; // 报错
 
 报错原因是,如果某个类型的所有属性都是可选的,那么该类型的对象必须至少存在一个可选属性,不能所有可选属性都不存在。这就叫做“最小可选属性规则”。
 
-如果想规避这条规则,要么在类型里面增加一条索性属性(`[propName: string]: someType`),要么使用类型断言(`opts as Options`)。
+如果想规避这条规则,要么在类型里面增加一条索引属性(`[propName: string]: someType`),要么使用类型断言(`opts as Options`)。
 
 ## 空对象
 

From 947d40e393a509275bb5e9e7364d02cbccb344b3 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 20 Aug 2023 17:23:24 +0800
Subject: [PATCH 055/120] docs(enum): fix enum overhaul

---
 docs/enum.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/enum.md b/docs/enum.md
index d0e101b..4f9ddf1 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -107,7 +107,7 @@ compute(Operator.ADD, 1, 3) // 4
 
 上面示例中,Enum 结构`Operator`的四个成员表示四则运算“加减乘除”。代码根本不需要用到这四个成员的值,只用成员名就够了。
 
-Enum 作为类型有一个缺点,就是输入任何数值都不报错。
+[TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#enum-overhaul) 之前,Enum 有一个 Bug,就是 Enum 类型的变量可以赋值为任何数值。
 
 ```typescript
 enum Bool {
@@ -119,10 +119,10 @@ function foo(noYes:Bool) {
   // ...
 }
 
-foo(33);  // 不报错
+foo(33);  // TypeScript 5.0 之前不报错
 ```
 
-上面代码中,函数`foo`的参数`noYes`只有两个可用的值,但是输入任意数值,编译都不会报错。
+上面示例中,函数`foo`的参数`noYes`是 Enum 类型,只有两个可用的值。但是,TypeScript 5.0 之前,任何数值作为函数`foo`的参数,编译都不会报错,TypeScript 5.0 纠正了这个问题。
 
 另外,由于 Enum 结构编译后是一个对象,所以不能有与它同名的变量(包括对象、函数、类等)。
 

From e0cd6ed70f6e85e14dfe4f981bb831219b28070b Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 20 Aug 2023 18:45:38 +0800
Subject: [PATCH 056/120] docs(class): fix #60

---
 docs/class.md | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index 66e5da9..c399e66 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -498,7 +498,7 @@ interface Swimmable {
 
 ### 类与接口的合并
 
-TypeScript 不允许两个同名的类,但是如果一个类和一个接口同名,那么接口会被合并进类。值得注意的是,合并进类的非空属性,在实际使用中可能为空。
+TypeScript 不允许两个同名的类,但是如果一个类和一个接口同名,那么接口会被合并进类。
 
 ```typescript
 class A {
@@ -510,8 +510,6 @@ interface A {
 }
 
 let a = new A();
-a.y // undefined
-
 a.y = 10;
 
 a.x // 1
@@ -520,6 +518,23 @@ a.y // 10
 
 上面示例中,类`A`与接口`A`同名,后者会被合并进前者的类型定义。
 
+注意,合并进类的非空属性(上例的`y`),如果在赋值之前读取,会返回`undefined`。
+
+```typescript
+class A {
+  x:number = 1;
+}
+
+interface A {
+  y:number;
+}
+
+let a = new A();
+a.y // undefined
+```
+
+上面示例中,根据类型定义,`y`应该是一个非空属性。但是合并后,`y`有可能是`undefined`。
+
 ## Class 类型
 
 ### 实例类型

From 885e90611899c5526a6a848246adbd981e0da173 Mon Sep 17 00:00:00 2001
From: VikydZhang <zwj_fhys@qq.com>
Date: Mon, 21 Aug 2023 15:46:58 +0800
Subject: [PATCH 057/120] Update interface.md

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index cf2943f..223d143 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -516,7 +516,7 @@ s.area;   // bigint | number
 
 `interface`命令与`type`命令作用类似,都可以表示对象类型。
 
-很多对象类型即可以用 interface 表示,也可以用 type 表示。而且,两者往往可以换用,几乎所有的 interface 命令都可以改写为 type 命令。
+很多对象类型既可以用 interface 表示,也可以用 type 表示。而且,两者往往可以换用,几乎所有的 interface 命令都可以改写为 type 命令。
 
 它们的相似之处,首先表现在都能为对象类型起名。
 

From ec0a6ded25fa874eac55d957846cfb1a997874ca Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 21 Aug 2023 23:26:48 +0800
Subject: [PATCH 058/120] docs(operator): fix keyof

---
 docs/operator.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index 15e096a..b7c0d38 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -148,7 +148,8 @@ function prop(obj, key) {
 
 ```javascript
 function prop(
-  obj:object, key:string
+  obj: { [p:string]: any },
+  key: string
 ):any {
   return obj[key];
 }

From abcc074a2cad08661f87d02bd08b47e4a2cc2d74 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 21 Aug 2023 23:46:26 +0800
Subject: [PATCH 059/120] docs(mapping): fix typo

---
 docs/mapping.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/mapping.md b/docs/mapping.md
index 8cf9bb2..91eec1f 100644
--- a/docs/mapping.md
+++ b/docs/mapping.md
@@ -342,7 +342,7 @@ type MyEvents<Events extends { kind: string }> = {
   [E in Events as E['kind']]: (event: E) => void;
 }
 
-type Config = MyEvent<S|C>;
+type Config = MyEvents<S|C>;
 // 等同于
 type Config = {
   square: (event:S) => void;

From 5459b3c348f3faa6b2f95a27f9c3406b2376f29d Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 22 Aug 2023 00:06:03 +0800
Subject: [PATCH 060/120] docs(types): fixed #64

---
 docs/types.md | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/docs/types.md b/docs/types.md
index dac280c..c05c8d1 100644
--- a/docs/types.md
+++ b/docs/types.md
@@ -129,9 +129,11 @@ const x:null = null;
 
 上面示例中,变量`x`就属于 null 类型。
 
-注意,如果没有声明类型的变量,被赋值为`undefined`或`null`,它们的类型会被推断为`any`。
+注意,如果没有声明类型的变量,被赋值为`undefined`或`null`,在关闭编译设置`noImplicitAny`和`strictNullChecks`时,它们的类型会被推断为`any`。
 
 ```typescript
+// 关闭 noImplicitAny 和 strictNullChecks
+
 let a = undefined;   // any
 const b = undefined; // any
 
@@ -143,6 +145,7 @@ const d = null;      // any
 
 ```typescript
 // 打开编译设置 strictNullChecks
+
 let a = undefined;   // undefined
 const b = undefined; // undefined
 

From 22ec0daf9539cc767bbf2886d2fb422d9e4109a4 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 22 Aug 2023 00:21:58 +0800
Subject: [PATCH 061/120] docs(tsconfig.json): fix jsx

---
 docs/tsconfig.json.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 3f48c12..02a887a 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -347,11 +347,13 @@ obj.foo = undefined; // 报错
 
 ### jsx
 
-`jsx`设置如何处理`.tsx`文件。它一般以下三个值。
+`jsx`设置如何处理`.tsx`文件。它可以取以下五个值。
 
-- `preserve`:保持 jsx 语法不变,输出的文件名为 jsx。
+- `preserve`:保持 jsx 语法不变,输出的文件名为`.jsx`。
 - `react`:将`<div />`编译成`React.createElement("div")`,输出的文件名为`.js`。
 - `react-native`:保持 jsx 语法不变,输出的文件后缀名为`.js`。
+- `react-jsx`:将`<div />`编译成`_jsx("div")`,输出的文件名为`.js`。
+- `react-jsxdev`:跟`react-jsx`类似,但是为`_jsx()`加上更多的开发调试项,输出的文件名为`.js`。
 
 ```javascript
 {

From 7a4164fabf9e39baac6be8b3623b7e4d7610c867 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 23 Aug 2023 09:39:02 +0800
Subject: [PATCH 062/120] docs(tuple): modify text

---
 docs/tuple.md | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/docs/tuple.md b/docs/tuple.md
index 8bff1d8..2f33475 100644
--- a/docs/tuple.md
+++ b/docs/tuple.md
@@ -4,7 +4,7 @@
 
 元组(tuple)是 TypeScript 特有的数据类型,JavaScript 没有单独区分这种类型。它表示成员类型可以自由设置的数组,即数组的各个成员的类型可以不同。
 
-元组必须明确声明每个成员的类型。
+由于成员的类型可以不一样,所以元组必须明确声明每个成员的类型。
 
 ```typescript
 const s:[string, string, boolean]
@@ -13,24 +13,26 @@ const s:[string, string, boolean]
 
 上面示例中,元组`s`的前两个成员的类型是`string`,最后一个成员的类型是`boolean`。
 
-元组类型的写法,与上一章的数组有一个重大差异。数组的成员类型写在方括号外面(`number[]`),元组的成员类型是写在方括号里面(`[number]`)。
-
-TypeScript 的区分方法是,成员类型写在方括号里面的就是元组,写在外面的就是数组。
+元组类型的写法,与上一章的数组有一个重大差异。数组的成员类型写在方括号外面(`number[]`),元组的成员类型是写在方括号里面(`[number]`)。TypeScript 的区分方法就是,成员类型写在方括号里面的就是元组,写在外面的就是数组。
 
 ```typescript
-let a:[number] = [1];
+// 数组
+let a:number[] = [1];
+
+// 元组
+let t:[number] = [1];
 ```
 
-上面示例中,变量`a`是一个元组,只有一个成员,类型是`number`。
+上面示例中,变量`a`和`t`的值都是`[1]`,但是它们的类型是不一样的。`a`是一个数组,成员类型`number`写在方括号外面;`t`是一个元组,成员类型`number`写在方括号里面。
 
 使用元组时,必须明确给出类型声明(上例的`[number]`),不能省略,否则 TypeScript 会把一个值自动推断为数组。
 
 ```typescript
-// a 的类型为 (number | boolean)[]
+// a 的类型被推断为 (number | boolean)[]
 let a = [1, true];
 ```
 
-上面示例中,变量`a`的值其实是一个元组,但是 TypeScript 会将其推断为一个联合类型的数组,即`a`的类型为`(number | boolean)[]`。
+上面示例中,变量`a`的值其实是一个元组,但是 TypeScript 会将其推断为一个联合类型的数组,即`a`的类型为`(number | boolean)[]`。所以,元组必须显式给出类型声明。
 
 元组成员的类型可以添加问号后缀(`?`),表示该成员是可选的。
 
@@ -77,7 +79,7 @@ const b:NamedNums = ['B', 1, 2, 3];
 
 上面示例中,元组类型`NamedNums`的第一个成员是字符串,后面的成员使用扩展运算符来展开一个数组,从而实现了不定数量的成员。
 
-扩展运算符用在元组的任意位置都可以,但是它后面只能是数组或元组。
+扩展运算符(`...`)用在元组的任意位置都可以,它的后面只能是一个数组或元组。
 
 ```typescript
 type t1 = [string, number, ...boolean[]];
@@ -85,7 +87,7 @@ type t2 = [string, ...boolean[], number];
 type t3 = [...boolean[], string, number];
 ```
 
-上面示例中,扩展运算符分别在元组的尾部、中部和头部。
+上面示例中,扩展运算符分别在元组的尾部、中部和头部,`...`的后面是一个数组`boolean[]`。
 
 如果不确定元组成员的类型和数量,可以写成下面这样。
 
@@ -95,6 +97,20 @@ type Tuple = [...any[]];
 
 上面示例中,元组`Tuple`可以放置任意数量和类型的成员。但是这样写,也就失去了使用元组和 TypeScript 的意义。
 
+元组的成员可以添加成员名,这个成员名是说明性的,可以任意取名,没有实际作用。
+
+```typescript
+type Color = [
+  red: number,
+  green: number,
+  blue: number
+];
+
+const c:Color = [255, 255, 255];
+```
+
+上面示例中,类型`Color`是一个元组,它有三个成员。每个成员都有一个名字,写在具体类型的前面,使用冒号分隔。这几个名字可以随便取,没有实际作用,只是用来说明每个成员的含义。
+
 元组可以通过方括号,读取成员类型。
 
 ```typescript

From 238fd3184a5c5c5680c7ac293d2dd7defe12444a Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Wed, 23 Aug 2023 10:14:44 +0800
Subject: [PATCH 063/120] fix: typo

---
 docs/operator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index b7c0d38..edae897 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -376,7 +376,7 @@ type T2 = RegExp extends Animal ? number : string;
 
 上面示例中,`Dog`是`Animal`的子类型,所以`T1`的类型是`number`。`RegExp`不是`Animal`的子类型,所以`T2`的类型是`string`。
 
-一般来说,调换`extends`两侧类型,会返回相反的结果。举例来说,有两个类`Dog`和`Animal`,前者是后者的子类型,那么`Cat extends Animal`就为真,而`Animal extends Cat`就为伪。
+一般来说,调换`extends`两侧类型,会返回相反的结果。举例来说,有两个类`Cat`和`Animal`,前者是后者的子类型,那么`Cat extends Animal`就为真,而`Animal extends Cat`就为伪。
 
 如果需要判断的类型是一个联合类型,那么条件运算符会展开这个联合类型。
 

From 5a1467469fb065992eab30456a5627d39f6b0d54 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Wed, 23 Aug 2023 14:22:14 +0800
Subject: [PATCH 064/120] fix: typo

---
 docs/mapping.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/mapping.md b/docs/mapping.md
index 91eec1f..6a9d44d 100644
--- a/docs/mapping.md
+++ b/docs/mapping.md
@@ -39,7 +39,7 @@ type B = {
 
 - `prop`:属性名变量,名字可以随便起。
 - `in`:运算符,用来取出右侧的联合类型的每一个成员。
-- `Keyof A`:返回类型`A`的每一个属性名,组成一个联合类型。
+- `keyof A`:返回类型`A`的每一个属性名,组成一个联合类型。
 
 下面是复制原始类型的例子。
 

From 0b265d2ca506a3f0b9c4324e72cd7df5e1073ab1 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Wed, 23 Aug 2023 14:34:06 +0800
Subject: [PATCH 065/120] fix: typo

---
 docs/mapping.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/mapping.md b/docs/mapping.md
index 6a9d44d..603ca9c 100644
--- a/docs/mapping.md
+++ b/docs/mapping.md
@@ -237,7 +237,7 @@ type A<T> = {
 };
 
 // 等同于
-type B<T> = {
+type A<T> = {
   readonly [P in keyof T]?: T[P];
 };
 ```

From 2e99e7459d2003fe8c25fd2b7eb940747e73b049 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 23 Aug 2023 15:39:31 +0800
Subject: [PATCH 066/120] docs(operator): add satisfies operator fixed #66

---
 docs/operator.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/docs/operator.md b/docs/operator.md
index b7c0d38..67edfa3 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -624,3 +624,73 @@ type V = `${T}${U}`;
 
 上面示例中,`T`和`U`都是联合类型,各自有两个成员,模板字符串里面引用了这两个类型,最后得到的就是一个4个成员的联合类型。
 
+## satisfies 运算符
+
+`satisfies`运算符用来检测某个值是否符合指定类型。有时候,不方便将某个值指定为某种类型,但是希望这个值符合类型条件,这时候就可以用`satisfies`运算符对其进行检测。[TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator)添加了这个运算符。
+
+举例来说,有一个对象的属性名拼写错误。
+
+```typescript
+const palette = {
+  red: [255, 0, 0],
+  green: "#00ff00",
+  bleu: [0, 0, 255] // 属性名拼写错误
+};
+```
+
+上面示例中,对象`palette`的属性名拼写错了,将`blue`拼成了`bleu`,我们希望通过指定类型,发现这个错误。
+
+```typescript
+type Colors = "red" | "green" | "blue";
+type RGB = [number, number, number];
+
+const palette: Record<Colors, string|RGB> = {
+  red: [255, 0, 0],
+  green: "#00ff00",
+  bleu: [0, 0, 255] // 报错
+};
+```
+
+上面示例中,变量`palette`的类型被指定为`Record<Colors, string|RGB>`,这是一个类型工具,用来返回一个对象,详细介绍见《类型工具》一章。简单说,它的第一个类型参数指定对象的属性名,第二个类型参数指定对象的属性值。
+
+本例的`Record<Colors, string|RGB>`,就表示变量`palette`的属性名应该符合类型`Colors`,属性值应该符合类型`string|RGB`,要么是字符串,要么是元组`RGB`。属性名`bleu`不符合类型`Colors`,所以就报错了。
+
+这样的写法,虽然可以发现属性名的拼写错误,但是带来了新的问题。
+
+```typescript
+const greenComponent = palette.green.substring(1, 6); // 报错
+```
+
+上面示例中,`palette.green`属性调用`substring()`方法会报错,原因是这个方法只有字符串才有,而`palette.green`的类型是`srting|RGB`,除了字符串,还可能是元组`RGB`,而元组并不存在`substring()`方法,所以报错了。
+
+如果要避免报错,要么精确给出变量`palette`每个属性的类型,要么对`palette.green`的值进行类型缩小。两种做法都比较麻烦,也不是很有必要。
+
+这时就可以使用`statisfies`运算符,对`palette`进行类型检测,但是不改变 TypeScript 对`palette`的类型推断。
+
+```typescript
+type Colors = "red" | "green" | "blue";
+type RGB = [number, number, number];
+
+const palette = {
+  red: [255, 0, 0],
+  green: "#00ff00",
+  bleu: [0, 0, 255] // 报错
+} satisfies Record<Colors, string|RGB>;
+
+const greenComponent = palette.green.substring(1); // 不报错
+```
+
+上面示例中,变量`palette`的值后面增加了`satisfies Record<Colors, string|RGB>`,表示该值必须满足`Record<Colors, string|RGB>`这个条件,所以能够检测出属性名`bleu`的拼写错误。同时,它不会改变`palette`的类型推断,所以,TypeScript 知道`palette.green`是一个字符串,对其调用`substring()`方法就不会报错。
+
+`statisfies`也可以检测属性值。
+
+```typescript
+const palette = {
+  red: [255, 0, 0],
+  green: "#00ff00",
+  blue: [0, 0] // 报错
+} satisfies Record<Colors, string|RGB>;
+```
+
+上面示例中,属性`blue`的值只有两个成员,不符合元组`RGB`必须有三个成员的条件,从而报错了。
+

From a3ca89fcb25612385c4926f3b3d96702a7d4cf52 Mon Sep 17 00:00:00 2001
From: nocodeempire <tioy102@gmail.com>
Date: Wed, 23 Aug 2023 16:56:49 +0800
Subject: [PATCH 067/120] fix: typo

---
 docs/operator.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/operator.md b/docs/operator.md
index e7596a3..56fffdf 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -665,7 +665,7 @@ const greenComponent = palette.green.substring(1, 6); // 报错
 
 如果要避免报错,要么精确给出变量`palette`每个属性的类型,要么对`palette.green`的值进行类型缩小。两种做法都比较麻烦,也不是很有必要。
 
-这时就可以使用`statisfies`运算符,对`palette`进行类型检测,但是不改变 TypeScript 对`palette`的类型推断。
+这时就可以使用`satisfies`运算符,对`palette`进行类型检测,但是不改变 TypeScript 对`palette`的类型推断。
 
 ```typescript
 type Colors = "red" | "green" | "blue";
@@ -682,7 +682,7 @@ const greenComponent = palette.green.substring(1); // 不报错
 
 上面示例中,变量`palette`的值后面增加了`satisfies Record<Colors, string|RGB>`,表示该值必须满足`Record<Colors, string|RGB>`这个条件,所以能够检测出属性名`bleu`的拼写错误。同时,它不会改变`palette`的类型推断,所以,TypeScript 知道`palette.green`是一个字符串,对其调用`substring()`方法就不会报错。
 
-`statisfies`也可以检测属性值。
+`satisfies`也可以检测属性值。
 
 ```typescript
 const palette = {

From 7a31fb834909c0a711151b1c9110d0de531163c7 Mon Sep 17 00:00:00 2001
From: Jacky Song <savesong@hotmail.com>
Date: Fri, 25 Aug 2023 16:19:28 +0800
Subject: [PATCH 068/120] docs(basic): fix typo

---
 docs/basic.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/basic.md b/docs/basic.md
index d86437f..4b943aa 100644
--- a/docs/basic.md
+++ b/docs/basic.md
@@ -69,7 +69,7 @@ function toString(num:number) {
 
 上面示例中,函数`toString()`没有声明返回值的类型,但是 TypeScript 推断返回的是字符串。正是因为 TypeScript 的类型推断,所以函数返回值的类型通常是省略不写的。
 
-从这里可以看到,TypeScript 的设计思想是,类型声明是可选的,你可以加,也可以不加。即使不加类型声明,依然是有效的 TypeScript 代码,只是这时不能保证 TypeScript 会正确推断出类型。由于这个原因。所有 JavaScript 代码都是合法的 TypeScript 代码。
+从这里可以看到,TypeScript 的设计思想是,类型声明是可选的,你可以加,也可以不加。即使不加类型声明,依然是有效的 TypeScript 代码,只是这时不能保证 TypeScript 会正确推断出类型。由于这个原因,所有 JavaScript 代码都是合法的 TypeScript 代码。
 
 这样设计还有一个好处,将以前的 JavaScript 项目改为 TypeScript 项目时,你可以逐步地为老代码添加类型,即使有些代码没有添加,也不会无法运行。
 

From 80afd4cf5c5d91fcdf5faa0e150063fc46855e00 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 26 Aug 2023 22:38:21 +0800
Subject: [PATCH 069/120] docs(function): modify never type

---
 docs/function.md | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/docs/function.md b/docs/function.md
index 48f456f..1d95ad5 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -546,7 +546,7 @@ function f():void {
 }
 ```
 
-需要特别注意的是,如果变量、对象方法、函数参数的类型是 void 类型的函数,那么并不代表不能赋值为有返回值的函数。恰恰相反,该变量、对象方法和函数参数可以接受返回任意值的函数,这时并不会报错。
+需要特别注意的是,如果变量、对象方法、函数参数是一个返回值为 void 类型的函数,那么并不代表不能赋值为有返回值的函数。恰恰相反,该变量、对象方法和函数参数可以接受返回任意值的函数,这时并不会报错。
 
 ```typescript
 type voidFunc = () => void;
@@ -556,7 +556,7 @@ const f:voidFunc = () => {
 };
 ```
 
-上面示例中,变量`f`的类型是`voidFunc`,是一个没有返回值的函数类型。但是实际上,`f`的值是一个有返回值的函数(返回`123`),编译时不会报错。
+上面示例中,变量`f`的类型是`voidFunc`,是一个没有返回值的函数。但是实际上,`f`的值可以是一个有返回值的函数(返回`123`),编译时不会报错。
 
 这是因为,这时 TypeScript 认为,这里的 void 类型只是表示该函数的返回值没有利用价值,或者说不应该使用该函数的返回值。只要不用到这里的返回值,就不会报错。
 
@@ -601,6 +601,16 @@ const f3 = function ():void {
 
 上面示例中,函数字面量声明了返回`void`类型,这时只要有返回值(除了`undefined`和`null`)就会报错。
 
+函数的运行结果如果是抛错,也允许将返回值写成`void`。
+
+```typescript
+function throwErr():void {
+  throw new Error('something wrong');
+}
+```
+
+上面示例中,函数`throwErr()`会抛错,返回值类型写成`void`是允许的。
+
 除了函数,其他变量声明为`void`类型没有多大意义,因为这时只能赋值为`undefined`或者`null`(假定没有打开`strictNullChecks`) 。
 
 ```typescript
@@ -636,6 +646,8 @@ function fail():Error {
 
 上面示例中,函数`fail()`返回一个 Error 对象,所以返回值类型是 Error。
 
+另外,由于抛错的情况属于`never`类型或`void`类型,所以无法从返回值类型中获知,抛出的是哪一种错误。
+
 (2)无限执行的函数。
 
 ```typescript
@@ -684,6 +696,24 @@ function f(
 
 上面示例中,函数`f()`的参数`x`的类型为`string|undefined`。但是,`x`类型为`undefined`时,调用了`neverReturns()`。这个函数不会返回,因此 TypeScript 可以推断出,判断语句后面的那个`x`,类型一定是`string`。
 
+一个函数如果某些条件下有正常返回值,另一些条件下抛错,这时它的返回值类型可以省略`never`。
+
+```typescript
+function sometimesThrow():number {
+  if (Math.random() > 0.5) {
+    return 100;
+  }
+
+  throw new Error('Something went wrong');
+}
+
+const result = sometimesThrow();
+```
+
+上面示例中,函数`sometimesThrow()`的返回值其实是`number|never`,但是一般都写成`number`,包括最后一行的变量`result`的类型,也是被推断为`number`。
+
+原因是前面章节提到过,`never`是 TypeScript 的唯一一个底层类型,所有其他类型都包括了`never`。从集合论的角度看,`number|never`等同于`number`。这也提示我们,函数的返回值无论是什么类型,都可能包含了抛出错误的情况。
+
 ## 局部类型
 
 函数内部允许声明其他类型,该类型只在函数内部有效,称为局部类型。

From 49850193149202c8c538b3df191fa1a65c310146 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 27 Aug 2023 00:14:14 +0800
Subject: [PATCH 070/120] docs(class): fix indexed property

---
 docs/class.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index c399e66..7ad78d9 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -287,19 +287,19 @@ class MyClass {
 }
 ```
 
-属性存取器等同于方法,也必须包括在属性索引里面。
+属性存取器视同属性。
 
 ```typescript
 class MyClass {
   [s:string]: boolean;
 
-  get(s:string) { // 报错
-    return this[s] as boolean;
+  get isInstance() {
+    return true;
   }
 }
 ```
 
-上面示例中,属性索引没有给出方法的类型,导致`get()`方法报错。正确的写法就是本节一开始的那个例子。
+上面示例中,属性`inInstance`的读取器虽然是一个函数方法,但是视同属性,所以属性索引虽然没有涉及方法类型,但是不会报错。
 
 ## 类的 interface 接口
 

From a56d4e1928df1e959a4267352000164ce23a2b6c Mon Sep 17 00:00:00 2001
From: 95cc <71340227+95cc@users.noreply.github.com>
Date: Sun, 27 Aug 2023 14:54:03 +0800
Subject: [PATCH 071/120] docs(tsconfig.json): fix typo

---
 docs/tsconfig.json.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 02a887a..7a86b4b 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -645,7 +645,7 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 
 `strictBindCallApply`设置是否对函数的`call()`、`bind()`、`apply()`这三个方法进行类型检查。
 
-如果不打开`strictBindCallApply`编译选项,编译器不会对以三个方法进行类型检查,参数类型都是`any`,传入任何参数都不会产生编译错误。
+如果不打开`strictBindCallApply`编译选项,编译器不会对以上三个方法进行类型检查,参数类型都是`any`,传入任何参数都不会产生编译错误。
 
 ```typescript
 function fn(x: string) {

From 0d4d9586cbaed64658de1a511b3a8c7dc6aff09c Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 27 Aug 2023 20:10:31 +0800
Subject: [PATCH 072/120] docs(enum): fix typo

---
 docs/enum.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/enum.md b/docs/enum.md
index 4f9ddf1..fed20c8 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -153,7 +153,7 @@ const Bar = {
   C: 2,
 } as const;
 
-if (x === Foo.A){}
+if (x === Foo.A) {}
 // 等同于
 if (x === Bar.A) {}
 ```

From 2c46d5a72a95f133b341ff3bc6d91bf06e159f8d Mon Sep 17 00:00:00 2001
From: alex12306 <zxc5305138@126.com>
Date: Tue, 29 Aug 2023 13:27:55 +0800
Subject: [PATCH 073/120] =?UTF-8?q?docs(interface):=E9=94=99=E5=88=AB?=
 =?UTF-8?q?=E5=AD=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index 223d143..b6dd5bc 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -113,7 +113,7 @@ const obj:A = ['a', 'b', 'c'];
 
 同样的,一个接口中最多只能定义一个数值索引。数值索引会约束所有名称为数值的属性。
 
-如果一个 interface 同时定义了字符串索引和数值索引,那么数值索性必须服从于字符串索引。因为在 JavaScript 中,数值属性名最终是自动转换成字符串属性名。
+如果一个 interface 同时定义了字符串索引和数值索引,那么数值索引必须服从于字符串索引。因为在 JavaScript 中,数值属性名最终是自动转换成字符串属性名。
 
 ```typescript
 interface A {

From eb982513008d8cceb43c21ab616d4ba98731bfc0 Mon Sep 17 00:00:00 2001
From: thinkasany <480968828@qq.com>
Date: Wed, 30 Aug 2023 09:55:33 +0800
Subject: [PATCH 074/120]    docs: perfect title

---
 docs/es6.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/es6.md b/docs/es6.md
index 1229e84..c9acdf8 100644
--- a/docs/es6.md
+++ b/docs/es6.md
@@ -44,7 +44,7 @@ async function fn(): Promise<number> {
 }
 ```
 
-## `Iterable<>`
+## `Iterable<T>`
 
 对象只要部署了 Iterator 接口,就可以用`for...of`循环遍历。Generator 函数(生成器)返回的就是一个具有 Iterator 接口的对象。
 

From 2fdbc00d73f6b1bcd741d057b3e346007f170e4c Mon Sep 17 00:00:00 2001
From: alex12306 <zxc5305138@126.com>
Date: Wed, 30 Aug 2023 14:43:03 +0800
Subject: [PATCH 075/120] =?UTF-8?q?docs:=20=E8=AE=A2=E6=AD=A3=EF=BC=9A?=
 =?UTF-8?q?=E7=AC=94=E8=AF=AF=E3=80=81=E5=85=A8=E8=A7=92=E5=88=86=E5=8F=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/mapping.md | 4 ++--
 docs/utility.md | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/mapping.md b/docs/mapping.md
index 603ca9c..ae1c0d7 100644
--- a/docs/mapping.md
+++ b/docs/mapping.md
@@ -113,7 +113,7 @@ type MyObj = {
 
 上面示例中,`[p in string]`就是属性名索引形式`[p: string]`的映射写法。
 
-通过映射,可以某个对象的所有属性改成可选属性。
+通过映射,可以把某个对象的所有属性改成可选属性。
 
 ```typescript
 type A = {
@@ -262,7 +262,7 @@ type B = {
 type B = {
   fooID: number;
   barID: number;
-};
+};
 ```
 
 上面示例中,类型`B`是类型`A`的映射,但在映射时把属性名改掉了,在原始属性名后面加上了字符串`ID`。
diff --git a/docs/utility.md b/docs/utility.md
index 62bdd64..46c64a0 100644
--- a/docs/utility.md
+++ b/docs/utility.md
@@ -660,7 +660,7 @@ type ThisParameterType<T> =
   T extends (
     this: infer U,
     ...args: never
-  ) => any ? U : unknown;
+  ) => any ? U : unknown;
 ```
 
 ## `ThisType<Type>`

From f78c771b24739092b08cc6c30887252064a01a58 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 31 Aug 2023 16:47:25 +0800
Subject: [PATCH 076/120] docs(module): fixed #76

---
 docs/module.md | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/docs/module.md b/docs/module.md
index ea6cc32..622f223 100644
--- a/docs/module.md
+++ b/docs/module.md
@@ -56,14 +56,6 @@ $ tsc b.ts
 
 上面命令发现`b.ts`依赖`a.ts`,就会自动寻找`a.ts`,也将其同时编译,因此编译产物还是`a.js`和`b.js`两个文件。
 
-如果想将`a.ts`和`b.ts`编译成一个文件,可以使用`--outFile`参数。
-
-```typescript
-$ tsc --outFile result.js b.ts
-```
-
-上面示例将`a.ts`和`b.ts`合并编译为`result.js`。
-
 ## import type 语句
 
 import 在一条语句中,可以同时输入类型和正常接口。

From 2b97ba6959d2ede2aa239a9cdc0f78410781043c Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Fri, 1 Sep 2023 22:08:25 +0800
Subject: [PATCH 077/120] chore: modify chapter title

---
 chapters.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/chapters.yml b/chapters.yml
index 14a2ffe..b1c1825 100644
--- a/chapters.yml
+++ b/chapters.yml
@@ -18,7 +18,7 @@
 - decorator-legacy.md: 装饰器(旧语法)
 - declare.md: declare 关键字
 - d.ts.md: d.ts 类型声明文件
-- operator.md: 运算符
+- operator.md: 类型运算符
 - mapping.md: 类型映射
 - utility.md: 类型工具
 - comment.md: 注释指令

From 663f3bfa049c45755427a4c62115544adedb528e Mon Sep 17 00:00:00 2001
From: thinkasany <480968828@qq.com>
Date: Sat, 2 Sep 2023 15:37:46 +0800
Subject: [PATCH 078/120] docs: perfect description

---
 docs/any.md      |  2 +-
 docs/function.md | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/docs/any.md b/docs/any.md
index 6026996..067e6e1 100644
--- a/docs/any.md
+++ b/docs/any.md
@@ -240,7 +240,7 @@ let v2:string = f(); // 不报错
 let v3:boolean = f(); // 不报错
 ```
 
-上面示例中,函数`f()`会抛错,所以返回值类型可以写成`never`,即不可能返回任何值。各种其他类型的变量都可以赋值为`f()`的运行结果(`never`类型)。
+上面示例中,函数`f()`会抛出错误,所以返回值类型可以写成`never`,即不可能返回任何值。各种其他类型的变量都可以赋值为`f()`的运行结果(`never`类型)。
 
 为什么`never`类型可以赋值给任意其他类型呢?这也跟集合论有关,空集是任何集合的子集。TypeScript 就相应规定,任何类型都包含了`never`类型。因此,`never`类型是任何其他类型所共有的,TypeScript 把这种情况称为“底层类型”(bottom type)。
 
diff --git a/docs/function.md b/docs/function.md
index 1d95ad5..f92e4c3 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -601,7 +601,7 @@ const f3 = function ():void {
 
 上面示例中,函数字面量声明了返回`void`类型,这时只要有返回值(除了`undefined`和`null`)就会报错。
 
-函数的运行结果如果是抛错,也允许将返回值写成`void`。
+函数的运行结果如果是抛出错误,也允许将返回值写成`void`。
 
 ```typescript
 function throwErr():void {
@@ -609,7 +609,7 @@ function throwErr():void {
 }
 ```
 
-上面示例中,函数`throwErr()`会抛错,返回值类型写成`void`是允许的。
+上面示例中,函数`throwErr()`会抛出错误,返回值类型写成`void`是允许的。
 
 除了函数,其他变量声明为`void`类型没有多大意义,因为这时只能赋值为`undefined`或者`null`(假定没有打开`strictNullChecks`) 。
 
@@ -634,7 +634,7 @@ function fail(msg:string):never {
 }
 ```
 
-上面示例中,函数`fail()`会抛错,不会正常退出,所以返回值类型是`never`。
+上面示例中,函数`fail()`会抛出错误,不会正常退出,所以返回值类型是`never`。
 
 注意,只有抛出错误,才是 never 类型。如果显式用`return`语句返回一个 Error 对象,返回值就不是 never 类型。
 
@@ -646,7 +646,7 @@ function fail():Error {
 
 上面示例中,函数`fail()`返回一个 Error 对象,所以返回值类型是 Error。
 
-另外,由于抛错的情况属于`never`类型或`void`类型,所以无法从返回值类型中获知,抛出的是哪一种错误。
+另外,由于抛出错误的情况属于`never`类型或`void`类型,所以无法从返回值类型中获知,抛出的是哪一种错误。
 
 (2)无限执行的函数。
 
@@ -696,7 +696,7 @@ function f(
 
 上面示例中,函数`f()`的参数`x`的类型为`string|undefined`。但是,`x`类型为`undefined`时,调用了`neverReturns()`。这个函数不会返回,因此 TypeScript 可以推断出,判断语句后面的那个`x`,类型一定是`string`。
 
-一个函数如果某些条件下有正常返回值,另一些条件下抛错,这时它的返回值类型可以省略`never`。
+一个函数如果某些条件下有正常返回值,另一些条件下抛出错误,这时它的返回值类型可以省略`never`。
 
 ```typescript
 function sometimesThrow():number {

From 65e5cbac3356f6b2e9f4cd2ba4dedc8bd9605774 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 2 Sep 2023 19:42:49 +0800
Subject: [PATCH 079/120] docs(tsconfig): moduleResolution add bundler

---
 docs/module.md        | 26 +++++++++++++++++---------
 docs/tsconfig.json.md |  3 ++-
 2 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/docs/module.md b/docs/module.md
index 622f223..fdbce43 100644
--- a/docs/module.md
+++ b/docs/module.md
@@ -223,17 +223,21 @@ console.log(obj.foo); // 123
 
 ## 模块定位
 
-模块定位(module resolution)指的是确定 import 语句和 export 语句里面的模块文件位置。
+模块定位(module resolution)指的是一种算法,用来确定 import 语句和 export 语句里面的模块文件位置。
 
 ```typescript
+// 相对模块
 import { TypeA } from './a';
+
+// 非相对模块
+import * as $ from "jquery";
 ```
 
-上面示例中,TypeScript 怎么确定`./a`到底是指哪一个模块,这就叫做“模块定位”。
+上面示例中,TypeScript 怎么确定`./a`或`jquery`到底是指哪一个模块,具体位置在哪里,用到的算法就叫做“模块定位”。
 
-模块定位有两种方法,一种称为 Classic 方法,另一种称为 Node 方法。可以使用编译参数`moduleResolution`,指定使用哪一种方法。
+编译参数`moduleResolution`,用来指定具体使用哪一种定位算法。常用的算法有两种:`Classic`和`Node`。
 
-没有指定定位方法时,就看原始脚本采用什么模块格式。如果模块格式是 CommonJS(即编译时指定`--module commonjs`),那么模块定位采用 Node 方法,否则采用 Classic 方法(模块格式为 es2015、 esnext、amd, system, umd 等等)。
+如果没有指定`moduleResolution`,它的默认值与编译参数`module`有关。`module`设为`commonjs`时(项目脚本采用 CommonJS 模块格式),`moduleResolution`的默认值为`Node`,即采用 Node.js 的模块定位算法。其他情况下(`module`设为 es2015、 esnext、amd, system, umd 等等),就采用`Classic`定位算法。
 
 ### 相对模块,非相对模块
 
@@ -245,26 +249,30 @@ import { TypeA } from './a';
 - `import { DefaultHeaders } from "../constants/http";`
 - `import "/mod";`
 
+相对模块的定位,是根据当前脚本的位置进行计算的,一般用于保存在当前项目目录结构中的模块脚本。
+
 非相对模块指的是不带有路径信息的模块。下面 import 语句加载的模块,都是非相对模块。
 
 - `import * as $ from "jquery";`
 - `import { Component } from "@angular/core";`
 
+非相对模块的定位,是由`baseUrl`属性或模块映射而确定的,通常用于加载外部模块。
+
 ### Classic 方法
 
 Classic 方法以当前脚本的路径作为“基准路径”,计算相对模块的位置。比如,脚本`a.ts`里面有一行代码`import { b } from "./b"`,那么 TypeScript 就会在`a.ts`所在的目录,查找`b.ts`和`b.d.ts`。
 
-至于非相对模块,也是以当前脚本的路径作为起点,一层层查找上级目录。比如,脚本`a.ts`里面有一行代码`import { b } from "b"`,那么就会查找`b.ts`和`b.d.ts`。
+至于非相对模块,也是以当前脚本的路径作为起点,一层层查找上级目录。比如,脚本`a.ts`里面有一行代码`import { b } from "b"`,那么就会依次在每一级上层目录里面,查找`b.ts`和`b.d.ts`。
 
 ### Node 方法
 
-Node 方法就是模拟 Node.js 的模块加载方法。
+Node 方法就是模拟 Node.js 的模块加载方法,也就是`require()`的实现方法。
 
 相对模块依然是以当前脚本的路径作为“基准路径”。比如,脚本文件`a.ts`里面有一行代码`let x = require("./b");`,TypeScript 按照以下顺序查找。
 
-1. 当前目录是否包含`b.ts`、`b.tsx`、`b.d.ts`。
-1. 当前目录是否有子目录`b`,该子目录是否存在文件`package.json`,该文件的`types`字段是否指定了入口文件,如果是的就加载该文件。
-1. 当前目录的子目录`b`是否包含`index.ts`、`index.tsx`、`index.d.ts`。
+1. 当前目录是否包含`b.ts`、`b.tsx`、`b.d.ts`。如果不存在就执行下一步。
+1. 当前目录是否存在子目录`b`,该子目录里面的`package.json`文件是否有`types`字段指定了模块入口文件。如果不存在就执行下一步。
+1. 当前目录的子目录`b`是否包含`index.ts`、`index.tsx`、`index.d.ts`。如果不存在就报错。
 
 非相对模块则是以当前脚本的路径作为起点,逐级向上层目录查找是否存在子目录`node_modules`。比如,脚本文件`a.js`有一行`let x = require("b");`,TypeScript 按照以下顺序进行查找。
 
diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 7a86b4b..76de0f4 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -449,8 +449,9 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 `moduleResolution`确定模块路径的算法,即如何查找模块。它可以取以下四种值。
 
 - `node`:采用 Node.js 的 CommonJS 模块算法。
-- `node16`或`nodenext`:采用 Node.js 的 ECMAScript 模块算法,从  TypeScript 4.7 开始支持。
+- `node16`或`nodenext`:采用 Node.js 的 ECMAScript 模块算法,从 TypeScript 4.7 开始支持。
 - `classic`:TypeScript 1.6 之前的算法,新项目不建议使用。
+- `bundle`:TypeScript 5.0 新增的选项,表示当前代码会被其他打包器(比如 Webpack、Vite、esbuild、Parcel、rollup、swc)处理,从而放宽加载规则,它要求`module`设为`es2015`或更高版本,详见加入该功能的 [PR 说明](https://github.com/microsoft/TypeScript/pull/51669)。
 
 它的默认值与`module`属性有关,如果`module`为`AMD`、`UMD`、`System`或`ES6/ES2015`,默认值为`classic`;如果`module`为`node16`或`nodenext`,默认值为这两个值;其他情况下,默认值为`Node`。
 

From 87034e4fcf34968e9111c3b3b60bee8625226a15 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 2 Sep 2023 19:44:28 +0800
Subject: [PATCH 080/120] docs(tsconfig): moduleResolution add bundler

---
 docs/tsconfig.json.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 76de0f4..7323e7d 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -451,7 +451,7 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 - `node`:采用 Node.js 的 CommonJS 模块算法。
 - `node16`或`nodenext`:采用 Node.js 的 ECMAScript 模块算法,从 TypeScript 4.7 开始支持。
 - `classic`:TypeScript 1.6 之前的算法,新项目不建议使用。
-- `bundle`:TypeScript 5.0 新增的选项,表示当前代码会被其他打包器(比如 Webpack、Vite、esbuild、Parcel、rollup、swc)处理,从而放宽加载规则,它要求`module`设为`es2015`或更高版本,详见加入该功能的 [PR 说明](https://github.com/microsoft/TypeScript/pull/51669)。
+- `bundler`:TypeScript 5.0 新增的选项,表示当前代码会被其他打包器(比如 Webpack、Vite、esbuild、Parcel、rollup、swc)处理,从而放宽加载规则,它要求`module`设为`es2015`或更高版本,详见加入该功能的 [PR 说明](https://github.com/microsoft/TypeScript/pull/51669)。
 
 它的默认值与`module`属性有关,如果`module`为`AMD`、`UMD`、`System`或`ES6/ES2015`,默认值为`classic`;如果`module`为`node16`或`nodenext`,默认值为这两个值;其他情况下,默认值为`Node`。
 

From 5732aca414709ce908ca4448277621ddcbf9d94a Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 9 Sep 2023 12:32:58 +0800
Subject: [PATCH 081/120] docs(function): edit function overload

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index f92e4c3..fd46274 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -889,7 +889,7 @@ type CreateElement = {
 }
 ```
 
-由于重载是一种比较复杂的类型声明方法,为了降低复杂性,一般来说,如果可以的话,应该优先使用联合类型替代函数重载。
+由于重载是一种比较复杂的类型声明方法,为了降低复杂性,一般来说,如果可以的话,应该优先使用联合类型替代函数重载,除非多个参数之间、或者某个参数与返回值之间,存在对应关系。
 
 ```typescript
 // 写法一

From 4583162ae56d0a2bc6ad08c9af1352d20b0ebafd Mon Sep 17 00:00:00 2001
From: biubiubiu999 <houshengaaa@gmail.com>
Date: Sun, 10 Sep 2023 00:13:09 +0800
Subject: [PATCH 082/120] Update operator.md

fix typo
---
 docs/operator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index 56fffdf..e892636 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -466,7 +466,7 @@ type Flatten<Type, Item> =
   Type extends Array<Item> ? Item : Type;
 ```
 
-上面是不使用`infer`的写法,每次调用`Fleatten`的时候,都要传入两个参数,就比较麻烦。
+上面是不使用`infer`的写法,每次调用`Flatten`的时候,都要传入两个参数,就比较麻烦。
 
 下面的例子使用`infer`,推断函数的参数类型和返回值类型。
 

From 5d83ec0e8b59d929d7dbf50bd868e682cd3966d4 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 10 Sep 2023 16:32:45 +0800
Subject: [PATCH 083/120] docs(tsconfig.json): edit typeRoots & types

---
 docs/tsconfig.json.md | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 7323e7d..daaed15 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -791,7 +791,9 @@ class User {
 
 ### typeRoots
 
-`typeRoots`设置类型模块所在的目录,默认是`node_modules/@types`。
+`typeRoots`设置类型模块所在的目录,默认是`node_modules/@types`,该目录里面的模块会自动加入编译。一旦指定了该属性,就不会再用默认值`node_modules/@types`里面的类型模块。
+
+该属性的值是一个数组,数组的每个成员就是一个目录,它们的路径是相对于`tsconfig.json`位置。
 
 ```typescript
 {
@@ -803,7 +805,7 @@ class User {
 
 ### types
 
-`types`设置`typeRoots`目录下需要包括在编译之中的类型模块。默认情况下,该目录下的所有类型模块,都会自动包括在编译之中。
+默认情况下,`typeRoots`目录下所有模块都会自动加入编译,如果指定了`types`属性,那么只有其中列出的模块才会自动加入编译。
 
 ```typescript
 {
@@ -813,6 +815,10 @@ class User {
 }
 ```
 
+上面的设置表示,默认情况下,只有`./node_modules/@types/node`、`./node_modules/@types/jest`和`./node_modules/@types/express`会自动加入编译,其他`node_modules/@types/`目录下的模块不会加入编译。
+
+如果`"types": []`,就表示不会自动将所有`@types`模块加入编译。
+
 ### useUnknownInCatchVariables
 
 `useUnknownInCatchVariables`设置`catch`语句捕获的`try`抛出的返回值类型,从`any`变成`unknown`。

From b567a611d4d66ded89f886f2cb76f1d4758add43 Mon Sep 17 00:00:00 2001
From: Cui Yang <cuiyang673308817@gmail.com>
Date: Fri, 15 Sep 2023 12:09:07 +0800
Subject: [PATCH 084/120] docs(function): fix typo

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index fd46274..1224f1c 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -571,7 +571,7 @@ const ret = [];
 src.forEach(el => ret.push(el));
 ```
 
-上面示例中,`push()`有返回值,表示新插入的元素在数组里面的位置。但是,对于`forEach()`方法来说,这个返回值是没有作用的,根本用不到,所以 TypeScript 不会报错。
+上面示例中,`push()`有返回值,表示插入新元素后数组的长度。但是,对于`forEach()`方法来说,这个返回值是没有作用的,根本用不到,所以 TypeScript 不会报错。
 
 如果后面使用了这个函数的返回值,就违反了约定,则会报错。
 

From 0e8f8a92fab6fe5955e3842ed2e6f580c7b0e6d4 Mon Sep 17 00:00:00 2001
From: weishen-hong <57124685+weihenHong@users.noreply.github.com>
Date: Fri, 15 Sep 2023 18:04:48 +0800
Subject: [PATCH 085/120] fix typo

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index b6dd5bc..a3b3a3f 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -526,7 +526,7 @@ type Country = {
   capital: string;
 }
 
-interface Coutry {
+interface Country {
   name: string;
   capital: string;
 }

From 8ad5fc69f7e19dd117ddfc60b3dee299afca0180 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 22 Nov 2023 00:07:23 +0800
Subject: [PATCH 086/120] docs(decorator): fixed #84

---
 docs/decorator.md | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/docs/decorator.md b/docs/decorator.md
index c8d0805..8aea41c 100644
--- a/docs/decorator.md
+++ b/docs/decorator.md
@@ -818,6 +818,9 @@ class T {
 
   @d('实例属性')
   instanceField = log('实例属性值');
+
+  @d('静态方法装饰器')
+  static fn(){}
 }
 ```
 
@@ -826,16 +829,18 @@ class T {
 它的运行结果如下。
 
 ```typescript
-// "评估 @d(): 类装饰器"
-// "评估 @d(): 静态属性装饰器"
-// "评估 @d(): 原型方法"
-// "计算方法名"
-// "评估 @d(): 实例属性"
-// "应用 @d(): 原型方法"
-// "应用 @d(): 静态属性装饰器"
-// "应用 @d(): 实例属性"
-// "应用 @d(): 类装饰器"
-// "静态属性值"
+评估 @d(): 类装饰器
+评估 @d(): 静态属性装饰器
+评估 @d(): 原型方法
+计算方法名
+评估 @d(): 实例属性
+评估 @d(): 静态方法装饰器
+应用 @d(): 静态方法装饰器
+应用 @d(): 原型方法
+应用 @d(): 静态属性装饰器
+应用 @d(): 实例属性
+应用 @d(): 类装饰器
+静态属性值
 ```
 
 可以看到,类载入的时候,代码按照以下顺序执行。
@@ -846,7 +851,7 @@ class T {
 
 (2)装饰器应用:实际执行装饰器函数,将它们与对应的方法和属性进行结合。
 
-原型方法的装饰器首先应用,然后是静态属性和静态方法装饰器,接下来是实例属性装饰器,最后是类装饰器。
+静态方法装饰器首先应用,然后是原型方法的装饰器和静态属性装饰器,接下来是实例属性装饰器,最后是类装饰器。
 
 注意,“实例属性值”在类初始化的阶段并不执行,直到类实例化时才会执行。
 

From 68962e8a1adfcb6573c51509c4ab1d86bf1eefab Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 23 Nov 2023 20:53:20 +0800
Subject: [PATCH 087/120] docs(enum): fix #85

---
 docs/enum.md | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/docs/enum.md b/docs/enum.md
index fed20c8..f9656b3 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -512,15 +512,14 @@ type Foo = keyof typeof MyEnum;
 
 上面示例中,`keyof typeof MyEnum`可以取出`MyEnum`的所有成员名,所以类型`Foo`等同于联合类型`'A'|'B'`。
 
-注意,这里的`typeof`是必需的,否则`keyof MyEnum`相当于`keyof number`。
+注意,这里的`typeof`是必需的,否则`keyof MyEnum`相当于`keyof string`。
 
 ```typescript
 type Foo = keyof MyEnum;
-// "toString" | "toFixed" | "toExponential" |
-// "toPrecision" | "valueOf" | "toLocaleString"
+// number | typeof Symbol.iterator | "toString" | "charAt" | "charCodeAt" | ...
 ```
 
-上面示例中,类型`Foo`等于类型`number`的所有原生属性名组成的联合类型。
+上面示例中,类型`Foo`等于类型`string`的所有原生属性名组成的联合类型。这是`MyEnum`为字符串 Enum 的结果,如果`MyEnum`是数值 Enum,那么`keyof MyEnum`相当于`keyof number`。
 
 这是因为 Enum 作为类型,本质上属于`number`或`string`的一种变体,而`typeof MyEnum`会将`MyEnum`当作一个值处理,从而先其转为对象类型,就可以再用`keyof`运算符返回该对象的所有属性名。
 

From a30b9442fc024a77c1a3a60478deb42194d5e8dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E6=98=BE?= <lixian@yuanian.com>
Date: Wed, 29 Nov 2023 16:39:41 +0800
Subject: [PATCH 088/120] fix: delete Superfluous words

---
 docs/tsconfig.json.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index daaed15..ce618c7 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -579,7 +579,7 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 
 ### rootDirs
 
-`rootDirs`把多个不同目录,合并成一个目虚拟目录,便于模块定位。
+`rootDirs`把多个不同目录,合并成一个虚拟目录,便于模块定位。
 
 ```typescript
 {

From abad608483dc32f7983b5141acbc57ae6eef5774 Mon Sep 17 00:00:00 2001
From: hermia <HQQhouqinqin0612@outlook.com>
Date: Thu, 30 Nov 2023 15:21:29 +0800
Subject: [PATCH 089/120] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=B9=E8=B1=A1?=
 =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E4=B8=AD=E5=B1=9E=E6=80=A7=E5=90=8D=E7=9A=84?=
 =?UTF-8?q?=E7=B4=A2=E5=BC=95=E7=B1=BB=E5=9E=8B=E4=B8=AD=E7=9A=84=E8=AF=AD?=
 =?UTF-8?q?=E4=B9=89=E9=94=99=E8=AF=AF=EF=BC=8C=E5=B0=86=E5=A6=82=E6=9E=9C?=
 =?UTF-8?q?=E5=8D=95=E4=B8=AA=E5=B1=9E=E6=80=A7=E5=90=8D=E7=AC=A6=20?=
 =?UTF-8?q?=E5=90=88=E5=B1=9E=E6=80=A7=E5=90=8D=E7=B4=A2=E5=BC=95=E7=9A=84?=
 =?UTF-8?q?=E8=8C=83=E5=9B=B4=EF=BC=8C=E4=B8=A4=E8=80=85=E4=B8=8D=E8=83=BD?=
 =?UTF-8?q?=E6=9C=89=E5=86=B2=E7=AA=81=EF=BC=8C=E5=90=A6=E5=88=99=E6=8A=A5?=
 =?UTF-8?q?=E9=94=99=E3=80=82=E4=BF=AE=E6=94=B9=E6=88=90=E5=A6=82=E6=9E=9C?=
 =?UTF-8?q?=E5=8D=95=E4=B8=AA=E5=B1=9E=E6=80=A7=E5=90=8D=E4=B8=8D=E7=AC=A6?=
 =?UTF-8?q?=E5=90=88=E5=B1=9E=E6=80=A7=E5=90=8D=E7=B4=A2=E5=BC=95=E7=9A=84?=
 =?UTF-8?q?=E8=8C=83=E5=9B=B4=EF=BC=8C=E4=B8=A4=E8=80=85=E5=8F=91=E7=94=9F?=
 =?UTF-8?q?=E5=86=B2=E7=AA=81=EF=BC=8C=E5=B0=B1=E4=BC=9A=E6=8A=A5=E9=94=99?=
 =?UTF-8?q?=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/object.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/object.md b/docs/object.md
index 8151363..3eb9bcb 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -423,7 +423,7 @@ type MyType = {
 
 上面示例中,类型`MyType`同时有两种属性名索引,但是数值索引与字符串索引冲突了,所以报错了。由于字符属性名的值类型是`string`,数值属性名的值类型只有同样为`string`,才不会报错。
 
-同样地,可以既声明属性名索引,也声明具体的单个属性名。如果单个属性名符合属性名索引的范围,两者不能有冲突,否则报错。
+同样地,可以既声明属性名索引,也声明具体的单个属性名。如果单个属性名不符合属性名索引的范围,两者发生冲突,就会报错。
 
 ```typescript
 type MyType = {

From d8b2606434740847951c9ee3ff5497203e6c575f Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 7 Dec 2023 10:34:26 +0800
Subject: [PATCH 090/120] docs(decorator): fix example

---
 docs/decorator.md | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/decorator.md b/docs/decorator.md
index 8aea41c..821a988 100644
--- a/docs/decorator.md
+++ b/docs/decorator.md
@@ -251,10 +251,10 @@ inst1.count // 1
 
 ```typescript
 function functionCallable(
-  value as any, {kind} as any
-) {
+  value:any, {kind}:any
+):any {
   if (kind === 'class') {
-    return function (...args) {
+    return function (...args:any) {
       if (new.target !== undefined) {
         throw new TypeError('This function can’t be new-invoked');
       }
@@ -265,10 +265,13 @@ function functionCallable(
 
 @functionCallable
 class Person {
-  constructor(name) {
+  name:string;
+  constructor(name:string) {
     this.name = name;
   }
 }
+
+// @ts-ignore
 const robin = Person('Robin');
 robin.name // 'Robin'
 ```

From f77f8d1b129acab42ac515e8981130ba9281fcab Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 11 Dec 2023 14:03:19 +0800
Subject: [PATCH 091/120] docs(declare): fixed #91

---
 docs/declare.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/declare.md b/docs/declare.md
index f1eb9b9..fde7dca 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -296,13 +296,13 @@ String.prototype.toSmallString = ():string => {
 
 这个示例第一行的空导出语句`export {}`,作用是强制编译器将这个脚本当作模块处理。这是因为`declare global`必须用在模块里面。
 
-下面的示例是为 window 对象添加一个属性`myAppConfig`。
+下面的示例是为 window 对象(类型接口为`Window`)添加一个属性`myAppConfig`。
 
 ```typescript
 export {};
 
 declare global {
-  interface window {
+  interface Window {
     myAppConfig:object;
   }
 }

From eb048a350909811c793a9aee6b3e53faaf3e5fbb Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 13 Dec 2023 13:53:59 +0800
Subject: [PATCH 092/120] docs: fixed #92

---
 docs/tsconfig.json.md | 2 +-
 docs/utility.md       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index ce618c7..b31d427 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -156,7 +156,7 @@ $ yarn add --dev @tsconfig/deno
 }
 ```
 
-## compileOptions
+## compilerOptions
 
 `compilerOptions`属性用来定制编译行为。这个属性可以省略,这时编译器将使用默认设置。
 
diff --git a/docs/utility.md b/docs/utility.md
index 46c64a0..0182f97 100644
--- a/docs/utility.md
+++ b/docs/utility.md
@@ -467,7 +467,7 @@ type Mutable<T> = {
 
 上面代码中,`-readonly`表示去除属性的只读标志。
 
-相应地,`+readonly`就表示增加只读标志,等同于`readonly`。因此,`ReadOnly<Type>`的实现也可以写成下面这样。
+相应地,`+readonly`就表示增加只读标志,等同于`readonly`。因此,`Readonly<Type>`的实现也可以写成下面这样。
 
 ```typescript
 type Readonly<T> = {

From 838b2f69f4ad91f907feaf20d7c39997713df56b Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 13 Dec 2023 14:19:00 +0800
Subject: [PATCH 093/120] docs(declare): fixed wrong example

---
 docs/declare.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/declare.md b/docs/declare.md
index fde7dca..ec85094 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -206,7 +206,7 @@ declare 关键字的另一个用途,是为外部模块添加属性和方法时
 import { Foo as Bar } from 'moduleA';
 
 declare module 'moduleA' {
-  interface Bar extends Foo {
+  interface Bar {
     custom: {
       prop1: string;
     }

From d21f77eebbc767596b185255b0459cd0a3917ed7 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 16 Dec 2023 11:14:14 +0800
Subject: [PATCH 094/120] docs(declare): fixed error

---
 docs/declare.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/declare.md b/docs/declare.md
index ec85094..960c20d 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -206,7 +206,7 @@ declare 关键字的另一个用途,是为外部模块添加属性和方法时
 import { Foo as Bar } from 'moduleA';
 
 declare module 'moduleA' {
-  interface Bar {
+  interface Foo {
     custom: {
       prop1: string;
     }
@@ -214,7 +214,7 @@ declare module 'moduleA' {
 }
 ```
 
-上面示例中,从模块`moduleA`导入了`Foo`接口,将其重命名为`Bar`,并用 declare 关键字为`Bar`增加一个属性`custom`。
+上面示例中,从模块`moduleA`导入了类型`Foo`,它是一个接口(interface),并将其重命名为`Bar`,然后用 declare 关键字为`Foo`增加一个属性`custom`。这里需要注意的是,虽然接口`Foo`改名为`Bar`,但是扩充类型时,还是扩充原始的接口`Foo`,因为同名 interface 会自动合并类型声明。
 
 下面是另一个例子。一个项目有多个模块,可以在一个模块中,对另一个模块的接口进行类型扩展。
 

From ef7d6197955c55eaa2c364114eaf04d3074b08eb Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 16 Dec 2023 14:51:21 +0800
Subject: [PATCH 095/120] docs: fixed typos

---
 docs/comment.md       | 2 +-
 docs/tsconfig.json.md | 2 +-
 docs/utility.md       | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/comment.md b/docs/comment.md
index 38ddfa7..126cbe7 100644
--- a/docs/comment.md
+++ b/docs/comment.md
@@ -55,8 +55,8 @@ function doStuff(abc: string, xyz: string) {
   // do some stuff
 }
 
-// @ts-expect-error
 expect(() => {
+  // @ts-expect-error
   doStuff(123, 456);
 }).toThrow();
 ```
diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index b31d427..93f7add 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -629,7 +629,7 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 - strictPropertyInitialization
 - noImplicitAny
 - noImplicitThis
-- useUnknownInCatchVaria
+- useUnknownInCatchVariables
 
 打开`strict`的时候,允许单独关闭其中一项。
 
diff --git a/docs/utility.md b/docs/utility.md
index 0182f97..d177337 100644
--- a/docs/utility.md
+++ b/docs/utility.md
@@ -644,7 +644,7 @@ type ReturnType<
 `ThisParameterType<Type>`提取函数类型中`this`参数的类型。
 
 ```typescript
-function toHex(this: Number) {
+function toHex(this:number) {
   return this.toString(16);
 }
 

From 68da0fb373aa5b82900d76340e5f1fcd0144458b Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 21 Dec 2023 22:48:08 +0800
Subject: [PATCH 096/120] docs(decorator): fixed #93

---
 docs/decorator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/decorator.md b/docs/decorator.md
index 821a988..8696b0e 100644
--- a/docs/decorator.md
+++ b/docs/decorator.md
@@ -691,7 +691,7 @@ class C {
 }
 ```
 
-上面示例中,`accessor`修饰符等同于为属性`x`自动生成取值器和存值器,它们作用于私有属性`x`。也就是说,上面的代码等同于下面的代码。
+上面示例中,`accessor`修饰符等同于为公开属性`x`自动生成取值器和存值器,它们作用于私有属性`x`。(注意,公开的`x`与私有的`x`不是同一个属性。)也就是说,上面的代码等同于下面的代码。
 
 ```typescript
 class C {

From 0299aa9604f775b673dfc9d69251ed2027a181bb Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 26 Dec 2023 22:37:03 +0800
Subject: [PATCH 097/120] docs(interface): fixed typo

---
 docs/interface.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/interface.md b/docs/interface.md
index a3b3a3f..e0169f8 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -394,7 +394,7 @@ interface Box {
 
 这样的设计主要是为了兼容 JavaScript 的行为。JavaScript 开发者常常对全局对象或者外部库,添加自己的属性和方法。那么,只要使用 interface 给出这些自定义属性和方法的类型,就能自动跟原始的 interface 合并,使得扩展外部类型非常方便。
 
-举例来说,Web 网页开发经常会对`windows`对象和`document`对象添加自定义属性,但是 TypeScript 会报错,因为原始定义没有这些属性。解决方法就是把自定义属性写成 interface,合并进原始定义。
+举例来说,Web 网页开发经常会对`window`对象和`document`对象添加自定义属性,但是 TypeScript 会报错,因为原始定义没有这些属性。解决方法就是把自定义属性写成 interface,合并进原始定义。
 
 ```typescript
 interface Document {

From 84474db9268b8c8f721a64f1a0584c80a914b121 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 9 Jan 2024 10:45:30 +0800
Subject: [PATCH 098/120] docs(module): fixed #96

---
 docs/module.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/module.md b/docs/module.md
index fdbce43..f481bc3 100644
--- a/docs/module.md
+++ b/docs/module.md
@@ -84,17 +84,19 @@ import { type A, a } from './a';
 
 上面示例中,import 语句输入的类型`A`前面有`type`关键字,表示这是一个类型。
 
-第二个方法是使用 import type 语句,这个语句只能输入类型,不能输入正常接口。
+第二个方法是使用 import type 语句,这个语句只用来输入类型,不用来输入正常接口。
 
 ```typescript
 // 正确
 import type { A } from './a';
+let b:A = 'hello';
 
 // 报错
 import type { a } from './a';
+let b = a;
 ```
 
-上面示例中,import type 输入类型`A`是正确的,但是输入正常接口`a`就会报错。
+上面示例中,import type 输入类型`A`是正确的,可以把`A`当作类型使用。但是,输入正常接口`a`,并把`a`当作一个值使用,就会报错。这就是说,看到`import type`,你就知道它输入的肯定是类型。
 
 import type 语句也可以输入默认类型。
 

From 4c7a0cbbebbb22ff84a9606934954fe552d6ac2b Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 18 Mar 2024 18:05:05 +0800
Subject: [PATCH 099/120] docs(assert): fixed #100

---
 docs/assert.md | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/docs/assert.md b/docs/assert.md
index 5c6659c..64aad74 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -114,15 +114,6 @@ const s2:string = value as string; // 正确
 
 上面示例中,unknown 类型的变量`value`不能直接赋值给其他类型的变量,但是可以将它断言为其他类型,这样就可以赋值给别的变量了。
 
-另外,类型断言也适合指定联合类型的值的具体类型。
-
-```typescript
-const s1:number|string = 'hello';
-const s2:number = s1 as number;
-```
-
-上面示例中,变量`s1`是联合类型,可以断言其为联合类型里面的一种具体类型,再将其赋值给变量`s2`。
-
 ## 类型断言的条件
 
 类型断言并不意味着,可以把某个值断言为任意类型。

From 5d4a2f1484facd2b4234e83f9e7ed851519e5797 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 19 Mar 2024 16:28:18 +0800
Subject: [PATCH 100/120] docs(operator): fixed #101

---
 docs/operator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index e892636..5416439 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -588,7 +588,7 @@ type Greeting = `hello ${World}`;
 
 上面示例中,类型`Greeting`是一个模板字符串,里面引用了另一个字符串类型`world`,因此`Greeting`实际上是字符串`hello world`。
 
-注意,模板字符串可以引用的类型一共6种,分别是 string、number、bigint、boolean、null、undefined。引用这6种以外的类型会报错。
+注意,模板字符串可以引用的类型一共7种,分别是 string、number、bigint、boolean、null、undefined、Enum。引用这7种以外的类型会报错。
 
 ```typescript
 type Num = 123;

From d5e0f47a20d1f2769dce610671a08033ac610d8e Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 21 Mar 2024 21:29:42 +0800
Subject: [PATCH 101/120] docs(function): fixed #102

---
 docs/function.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/docs/function.md b/docs/function.md
index 1224f1c..9badcf1 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -498,6 +498,8 @@ function arraySum(
 
 上面示例中,参数`arr`的类型是`readonly number[]`,表示为只读参数。如果函数体内部修改这个数组,就会报错。
 
+注意,`readonly`关键字目前只允许用在数组和元组类型的参数前面,如果用在其他类型的参数前面,就会报错。
+
 ## void 类型
 
 void 类型表示函数没有返回值。

From 57cdc82253554a4eaff53cb2fcf8d2ed06b87b34 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Wed, 10 Apr 2024 16:54:05 +0800
Subject: [PATCH 102/120] docs(function): fixed typo

---
 docs/function.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/function.md b/docs/function.md
index 9badcf1..6795e59 100644
--- a/docs/function.md
+++ b/docs/function.md
@@ -374,7 +374,7 @@ function f(x = 456) {
   return x;
 }
 
-f2(undefined) // 456
+f(undefined) // 456
 ```
 
 具有默认值的参数如果不位于参数列表的末尾,调用时不能省略,如果要触发默认值,必须显式传入`undefined`。

From ae9bea9a37872b5dcdca75800aa2dd211450d86f Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 23 May 2024 23:16:41 +0800
Subject: [PATCH 103/120] =?UTF-8?q?docs(declare):=20=E4=BF=AE=E6=94=B9?=
 =?UTF-8?q?=E4=B8=8D=E8=83=BD=E5=8D=95=E7=8B=AC=E5=86=99=E5=87=BD=E6=95=B0?=
 =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=A3=B0=E6=98=8E=E7=9A=84=E7=A4=BA=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 docs/declare.md | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/declare.md b/docs/declare.md
index 960c20d..ca7665a 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -82,7 +82,7 @@ declare function sayHello(
 sayHello('张三');
 ```
 
-上面示例中,declare 命令给出了`sayHello()`的类型描述,因此可以直接使用它。
+上面示例中,declare 命令给出了`sayHello()`的类型描述,表示这个函数是由外部文件定义的,因此这里可以直接使用该函数。
 
 注意,这种单独的函数类型声明语句,只能用于`declare`命令后面。一方面,TypeScript 不支持单独的函数类型声明语句;另一方面,declare 关键字后面也不能带有函数的具体实现。
 
@@ -91,7 +91,10 @@ sayHello('张三');
 function sayHello(
   name:string
 ):void;
-function sayHello(name) {
+
+let foo = 'bar';
+
+function sayHello(name:string) {
   return '你好,' + name;
 }
 ```

From 1605a244987f8e669e36662bb28b73530bd69ffb Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 8 Jun 2024 16:32:28 +0800
Subject: [PATCH 104/120] refactor: update dependencies

---
 package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 9848fbb..18efa39 100644
--- a/package.json
+++ b/package.json
@@ -20,8 +20,8 @@
   "author": "Ruan Yifeng",
   "license": "CC-BY-SA-4.0",
   "dependencies": {
-    "gh-pages": "^5.0.0",
+    "gh-pages": "6.x",
     "loppo": "^0.6.25",
-    "loppo-theme-wangdoc": "^0.6.6"
+    "loppo-theme-wangdoc": "^0.7.1"
   }
 }

From 22904d3e2db8be745d69f0f2f75c4b1c13e19ede Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 8 Jun 2024 16:38:16 +0800
Subject: [PATCH 105/120] refactor: update github action script

---
 .github/workflows/wangdoc.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/wangdoc.yml b/.github/workflows/wangdoc.yml
index 29b9a5b..8b652ac 100644
--- a/.github/workflows/wangdoc.yml
+++ b/.github/workflows/wangdoc.yml
@@ -10,11 +10,11 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           persist-credentials: false
       - name: Setup Node.js
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: 'latest'
       - name: Install dependencies

From f665b3f262b9d4922c95f30f428568183c6fff75 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 8 Jun 2024 16:40:18 +0800
Subject: [PATCH 106/120] docs(utility): fixed #107

---
 docs/utility.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/utility.md b/docs/utility.md
index d177337..af454c2 100644
--- a/docs/utility.md
+++ b/docs/utility.md
@@ -44,7 +44,7 @@ type Awaited<T> =
   } ? F extends (
     value: infer V,
     ...args: infer _
-  ) => any ? Awaited<...> : never:
+  ) => any ? Awaited<V> : never:
   T;
 ```
 

From 73e9fdc014eaa82a0ecfc05ee5485f64a7d20881 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 10 Jun 2024 07:47:18 +0800
Subject: [PATCH 107/120] docs(utility): edit text

---
 docs/utility.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/utility.md b/docs/utility.md
index af454c2..02a03f9 100644
--- a/docs/utility.md
+++ b/docs/utility.md
@@ -2,7 +2,7 @@
 
 TypeScript 提供了一些内置的类型工具,用来方便地处理各种类型,以及生成新的类型。
 
-TypeScript 内置了17个类型工具,可以直接使用。
+这些类型工具都是语言本身提供的,可以直接使用。
 
 ## `Awaited<Type>`
 

From 066605460981d30e3afea06ceab6b3df41737b09 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 22 Jun 2024 20:12:43 +0800
Subject: [PATCH 108/120] docs(object): fixed #109

---
 docs/object.md | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/docs/object.md b/docs/object.md
index 3eb9bcb..3141870 100644
--- a/docs/object.md
+++ b/docs/object.md
@@ -489,8 +489,7 @@ let { x: foo, y: bar }
 ```typescript
 function draw({
   shape: Shape,
-  xPos: number = 100,
-  yPos: number = 100
+  xPos: number = 100
 }) {
   let myShape = shape; // 报错
   let x = xPos; // 报错

From a7d9796ed5f544880fc03e2192ecf61f9789fa88 Mon Sep 17 00:00:00 2001
From: LOUSANPANG <36870764+LOUSANPANG@users.noreply.github.com>
Date: Thu, 27 Jun 2024 22:08:42 +0800
Subject: [PATCH 109/120] docs(class):correction words

"MotoVehicle" -> "MotorVehicle"
---
 docs/class.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index 7ad78d9..fe3b971 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -471,7 +471,7 @@ interface Swimmable {
   // ...
 }
 
-interface SuperCar extends MotoVehicle,Flyable, Swimmable {
+interface SuperCar extends MotorVehicle,Flyable, Swimmable {
   // ...
 }
 
@@ -570,7 +570,7 @@ const c1:Car = new Car();
 const c2:MotorVehicle = new Car();
 ```
 
-上面示例中,变量的类型可以写成类`Car`,也可以写成接口`MotorVehicle`。它们的区别是,如果类`Car`有接口`MotoVehicle`没有的属性和方法,那么只有变量`c1`可以调用这些属性和方法。
+上面示例中,变量的类型可以写成类`Car`,也可以写成接口`MotorVehicle`。它们的区别是,如果类`Car`有接口`MotorVehicle`没有的属性和方法,那么只有变量`c1`可以调用这些属性和方法。
 
 作为类型使用时,类名只能表示实例的类型,不能表示类的自身类型。
 

From bbde4688b44bda3e4390d4755e0648cec26a1505 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 1 Jul 2024 18:24:12 +0800
Subject: [PATCH 110/120] docs(class): modify useDefineForClassFields, fixed
 #113

---
 docs/class.md         | 193 +++++++++++++++++++++++++++++-------------
 docs/tsconfig.json.md |   6 ++
 2 files changed, 140 insertions(+), 59 deletions(-)

diff --git a/docs/class.md b/docs/class.md
index fe3b971..947c510 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -954,65 +954,6 @@ class Test extends getGreeterBase() {
 
 上面示例中,例一和例二的`extends`关键字后面都是构造函数,例三的`extends`关键字后面是一个表达式,执行后得到的也是一个构造函数。
 
-对于那些只设置了类型、没有初值的顶层属性,有一个细节需要注意。
-
-```typescript
-interface Animal {
-  animalStuff: any;
-}
-
-interface Dog extends Animal {
-  dogStuff: any;
-}
-
-class AnimalHouse {
-  resident: Animal;
-
-  constructor(animal:Animal) {
-    this.resident = animal;
-  }
-}
-
-class DogHouse extends AnimalHouse {
-  resident: Dog;
-
-  constructor(dog:Dog) {
-    super(dog);
-  }
-}
-```
-
-上面示例中,类`DogHouse`的顶层成员`resident`只设置了类型(`Dog`),没有设置初值。这段代码在不同的编译设置下,编译结果不一样。
-
-如果编译设置的`target`设成大于等于`ES2022`,或者`useDefineForClassFields`设成`true`,那么下面代码的执行结果是不一样的。
-
-```typescript
-const dog = {
-  animalStuff: 'animal',
-  dogStuff: 'dog'
-};
-
-const dogHouse = new DogHouse(dog);
-
-console.log(dogHouse.resident) // undefined
-```
-
-上面示例中,`DogHouse`实例的属性`resident`输出的是`undefined`,而不是预料的`dog`。原因在于 ES2022 标准的 Class Fields 部分,与早期的 TypeScript 实现不一致,导致子类的那些只设置类型、没有设置初值的顶层成员在基类中被赋值后,会在子类被重置为`undefined`,详细的解释参见《tsconfig.json》一章,以及官方 3.7 版本的[发布说明](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier)。
-
-解决方法就是使用`declare`命令,去声明顶层成员的类型,告诉 TypeScript 这些成员的赋值由基类实现。
-
-```typescript
-class DogHouse extends AnimalHouse {
-  declare resident: Dog;
-
-  constructor(dog:Dog) {
-    super(dog);
-  }
-}
-```
-
-上面示例中,`resident`属性的类型声明前面用了`declare`命令,这样就能确保在编译目标大于等于`ES2022`时(或者打开`useDefineForClassFields`时),代码行为正确。
-
 ## 可访问性修饰符
 
 类的内部成员的外部可访问性,由三个可访问性修饰符(access modifiers)控制:`public`、`private`和`protected`。
@@ -1278,6 +1219,140 @@ class A {
 }
 ```
 
+## 顶层属性的处理方法
+
+对于类的顶层属性,TypeScript 早期的处理方法,与后来的 ES2022 标准不一致。这会导致某些代码的运行结果不一样。
+
+类的顶层属性在 TypeScript 里面,有两种写法。
+
+```typescript
+class User {
+  // 写法一
+  age = 25;
+
+  // 写法二
+  constructor(private currentYear: number) {}
+}
+```
+
+上面示例中,写法一是直接声明一个实例属性`age`,并初始化;写法二是顶层属性的简写形式,直接将构造方法的参数`currentYear`声明为实例属性。
+
+TypeScript 早期的处理方法是,先在顶层声明属性,但不进行初始化,等到运行构造方法时,再完成所有初始化。
+
+```typescript
+class User {
+  age = 25;
+}
+
+// TypeScript 的早期处理方法
+class User {
+  age: number;
+
+  constructor() {
+    this.age = 25;
+  }
+}
+```
+
+上面示例中,TypeScript 早期会先声明顶层属性`age`,然后等到运行构造函数时,再将其初始化为`25`。
+
+ES2022 标准里面的处理方法是,先进行顶层属性的初始化,再运行构造方法。这在某些情况下,会使得同一段代码在 TypeScript 和 JavaScript 下运行结果不一致。
+
+这种不一致一般发生在两种情况。第一种情况是,顶层属性的初始化依赖于其他实例属性。
+
+```typescript
+class User {
+  age = this.currentYear - 1998;
+
+  constructor(private currentYear: number) {
+    // 输出结果将不一致
+    console.log('Current age:', this.age);
+  }
+}
+
+const user = new User(2023);
+```
+
+上面示例中,顶层属性`age`的初始化值依赖于实例属性`this.currentYear`。按照 TypeScript 的处理方法,初始化是在构造方法里面完成的,会输出结果为`25`。但是,按照 ES2022 标准的处理方法,初始化在声明顶层属性时就会完成,这时`this.currentYear`还等于`undefined`,所以`age`的初始化结果为`NaN`,因此最后输出的也是`NaN`。
+
+第二种情况与类的继承有关,子类声明的顶层属性在父类完成初始化。
+
+```typescript
+interface Animal {
+  animalStuff: any;
+}
+
+interface Dog extends Animal {
+  dogStuff: any;
+}
+
+class AnimalHouse {
+  resident: Animal;
+
+  constructor(animal:Animal) {
+    this.resident = animal;
+  }
+}
+
+class DogHouse extends AnimalHouse {
+  resident: Dog;
+
+  constructor(dog:Dog) {
+    super(dog);
+  }
+}
+```
+
+上面示例中,类`DogHouse`继承自`AnimalHouse`。它声明了顶层属性`resident`,但是该属性的初始化是在父类`AnimalHouse`完成的。不同的设置运行下面的代码,结果将不一致。
+
+```typescript
+const dog = {
+  animalStuff: 'animal',
+  dogStuff: 'dog'
+};
+
+const dogHouse = new DogHouse(dog);
+
+console.log(dogHouse.resident) // 输出结果将不一致
+```
+
+上面示例中,TypeScript 的处理方法,会使得`resident`属性能够初始化,所以输出参数对象的值。但是,ES2022 标准的处理方法是,顶层属性的初始化先于构造方法的运行。这使得`resident`属性不会得到赋值,因此输出为`undefined`。
+
+为了解决这个问题,同时保证以前代码的行为一致,TypeScript 从3.7版开始,引入了编译设置`useDefineForClassFields`。这个设置设为`true`,则采用 ES2022 标准的处理方法,否则采用 TypeScript 早期的处理方法。
+
+它的默认值与`target`属性有关,如果输出目标设为`ES2022`或者更高,那么`useDefineForClassFields`的默认值为`true`,否则为`false`。关于这个设置的详细说明,参见官方 3.7 版本的[发布说明](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier)。
+
+如果希望避免这种不一致,让代码在不同设置下的行为都一样,那么可以将所有顶层属性的初始化,都放到构造方法里面。
+
+```typescript
+class User  {
+  age: number;
+
+  constructor(private currentYear: number) {
+    this.age = this.currentYear - 1998;
+    console.log('Current age:', this.age);
+  }
+}
+
+const user = new User(2023);
+```
+
+上面示例中,顶层属性`age`的初始化就放在构造方法里面,那么任何情况下,代码行为都是一致的。
+
+对于类的继承,还有另一种解决方法,就是使用`declare`命令,去声明子类顶层属性的类型,告诉 TypeScript 这些属性的初始化由父类实现。
+
+```typescript
+class DogHouse extends AnimalHouse {
+  declare resident: Dog;
+
+  constructor(dog:Dog) {
+    super(dog);
+  }
+}
+```
+
+上面示例中,`resident`属性的类型声明前面用了`declare`命令。这种情况下,这一行代码在编译成 JavaScript 后就不存在,那么也就不会有行为不一致,无论是否设置`useDefineForClassFields`,输出结果都是一样的。
+
 ## 静态成员
 
 类的内部可以使用`static`关键字,定义静态成员。
diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 93f7add..ad4009a 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -819,6 +819,12 @@ class User {
 
 如果`"types": []`,就表示不会自动将所有`@types`模块加入编译。
 
+### useDefineForClassFields
+
+`useDefineForClassFields`这个设置针对的是,在类(class)的顶部声明的属性。TypeScript 早先对这一类属性的处理方法,与写入 ES2022 标准的处理方法不一致。这个设置设为`true`,就用来开启 ES2022 的处理方法,设为`false`就是 TypeScript 原有的处理方法。
+
+它的默认值跟`target`属性有关,如果编译目标是`ES2022`或更高,那么`useDefineForClassFields`默认值为`true`,否则为`false`。
+
 ### useUnknownInCatchVariables
 
 `useUnknownInCatchVariables`设置`catch`语句捕获的`try`抛出的返回值类型,从`any`变成`unknown`。

From 8f59ef87cf9fd37259a7e041251664718cc2c8fa Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 1 Jul 2024 18:29:04 +0800
Subject: [PATCH 111/120] docs(class): add reference link

---
 docs/class.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/docs/class.md b/docs/class.md
index 947c510..26c094d 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -1670,4 +1670,5 @@ class FileSystemObject {
 ## 参考链接
 
 - [TypeScript Constructor in Interface](http://fritzthecat-blog.blogspot.com/2018/06/typescript-constructor-in-interface.html)
+- [TypeScript: useDefineForClassFields – How to avoid future Breaking Changes](https://angular.schule/blog/2022-11-use-define-for-class-fields)
 

From dd06fc53e10ba25a83c24602a1ee438d0d5be58e Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 3 Aug 2024 01:19:54 +0800
Subject: [PATCH 112/120] docs(class): add override keyword #114

---
 docs/class.md | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/docs/class.md b/docs/class.md
index 26c094d..0ac8567 100644
--- a/docs/class.md
+++ b/docs/class.md
@@ -954,6 +954,48 @@ class Test extends getGreeterBase() {
 
 上面示例中,例一和例二的`extends`关键字后面都是构造函数,例三的`extends`关键字后面是一个表达式,执行后得到的也是一个构造函数。
 
+## override 关键字
+
+子类继承父类时,可以覆盖父类的同名方法。
+
+```typescript
+class A {
+  show() {
+    // ...
+  }
+  hide() {
+    // ...
+  }
+}
+class B extends A {
+  show() {
+    // ...
+  }
+  hide() {
+    // ...
+  }
+}
+```
+
+上面示例中,B 类定义了自己的`show()`方法和`hide()`方法,覆盖了 A 类的同名方法。
+
+但是有些时候,我们继承他人的类,可能会在不知不觉中,就覆盖了他人的方法。为了防止这种情况,TypeScript 4.3 引入了 [override 关键字](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html#override-and-the---noimplicitoverride-flag)。
+
+```typescript
+class B extends A {
+  override show() {
+    // ...
+  }
+  override hide() {
+    // ...
+  }
+}
+```
+
+上面示例中,B 类的`show()`方法和`hide()`方法前面加了 override 关键字,明确表明作者的意图,就是要覆盖 A 类里面的这两个同名方法。这时,如果 A 类没有定义自己的`show()`方法和`hide()`方法,就会报错。
+
+但是,这依然没有解决,子类无意中覆盖父类同名方法的问题。因此,TypeScript 又提供了一个编译参数`noImplicitOverride`。一旦打开这个参数,子类覆盖父类的同名方法就会报错,除非使用了 override 关键字。
+
 ## 可访问性修饰符
 
 类的内部成员的外部可访问性,由三个可访问性修饰符(access modifiers)控制:`public`、`private`和`protected`。

From b376397025c99b596a20b7d318f9ac8eed36e348 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 23 Sep 2024 11:08:00 +0800
Subject: [PATCH 113/120] docs(assert): fixed #119

---
 docs/assert.md | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/docs/assert.md b/docs/assert.md
index 64aad74..7026698 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -490,18 +490,9 @@ function assertIsDefined<T>(
 
 上面示例中,工具类型`NonNullable<T>`对应类型`T`去除空类型后的剩余类型。
 
-如果要将断言函数用于函数表达式,可以采用下面的写法。
+如果要将断言函数用于函数表达式,可以采用下面的写法。根据 TypeScript 的[要求](https://github.com/microsoft/TypeScript/pull/33622),这时函数表达式所赋予的变量,必须有明确的类型声明。
 
 ```typescript
-// 写法一
-const assertIsNumber = (
-  value:unknown
-):asserts value is number => {
-  if (typeof value !== 'number')
-    throw Error('Not a number');
-};
-
-// 写法二
 type AssertIsNumber =
   (value:unknown) => asserts value is number;
 

From f68cdbc9108f332ab1b78f4d1ac95059e9945edb Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Mon, 23 Sep 2024 11:12:42 +0800
Subject: [PATCH 114/120] docs(assert): edit reference link

---
 docs/assert.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/assert.md b/docs/assert.md
index 7026698..f816bab 100644
--- a/docs/assert.md
+++ b/docs/assert.md
@@ -490,7 +490,7 @@ function assertIsDefined<T>(
 
 上面示例中,工具类型`NonNullable<T>`对应类型`T`去除空类型后的剩余类型。
 
-如果要将断言函数用于函数表达式,可以采用下面的写法。根据 TypeScript 的[要求](https://github.com/microsoft/TypeScript/pull/33622),这时函数表达式所赋予的变量,必须有明确的类型声明。
+如果要将断言函数用于函数表达式,可以采用下面的写法。根据 TypeScript 的[要求](https://github.com/microsoft/TypeScript/pull/33622#issuecomment-575301357),这时函数表达式所赋予的变量,必须有明确的类型声明。
 
 ```typescript
 type AssertIsNumber =

From 5c56fd550e31dddfa3a735acdc9569a63d454e53 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sun, 29 Sep 2024 19:29:11 +0800
Subject: [PATCH 115/120] docs(enum): fixed #122

---
 docs/enum.md | 2 +-
 package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/enum.md b/docs/enum.md
index f9656b3..9b4127d 100644
--- a/docs/enum.md
+++ b/docs/enum.md
@@ -312,7 +312,7 @@ enum Foo {
 // 等同于
 enum Foo {
   A,
-  B = 1,
+  B = 1,
   C = 2
 }
 ```
diff --git a/package.json b/package.json
index 18efa39..f7f09b8 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,6 @@
   "dependencies": {
     "gh-pages": "6.x",
     "loppo": "^0.6.25",
-    "loppo-theme-wangdoc": "^0.7.1"
+    "loppo-theme-wangdoc": "^0.7.3"
   }
 }

From e7e1a775c8ea9610876ae9e736d1731aec220e83 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 3 Oct 2024 22:16:29 +0800
Subject: [PATCH 116/120] docs(tsconfig.json): edit strictNullChecks

---
 docs/tsconfig.json.md | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index ad4009a..a6b82db 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -677,28 +677,40 @@ let func:StringOrNumberFunc = fn;
 
 ### strictNullChecks
 
-`strictNullChecks`设置对`null`和`undefined`进行严格类型检查。如果打开`strict`属性,这一项就会自动设为`true`,否则为`false`。
+不打开`strictNullChecks`的情况下,变量可以设为`undefined`或`null`,而不管其类型是什么。
 
-```bash
-let value:string;
+```typescript
+// 不打开 strictNullChecks 的情况
+let x:number;
 
-// strictNullChecks:false
-// 下面语句不报错
-value = null;
+x = undefined; // 不报错
+x = null; // 不报错
 ```
 
-它可以理解成只要打开,就需要显式检查`null`或`undefined`。
+上面示例中,变量`x`的类型是`number`,但是赋值为`undefined`或`null`都不会报错。这是为了继承 JavaScript 的设定:当变量没有赋值时,它的值就为`undefined`。
+
+一旦打开`strictNullChecks`,就相当于从变量的值里面,排除了`undefined`和`null`,除非变量的类型是这两种类型。
 
 ```typescript
-function doSomething(x:string|null) {
-  if (x === null) {
-    // do nothing
-  } else {
-    console.log("Hello, " + x.toUpperCase());
-  }
-}
+// 打开 strictNullChecks 的情况
+let x:number;
+
+x = undefined; // 报错
+x = null; // 报错
 ```
 
+下面是一个例子。
+
+```typescript
+// 打开 strickNullChecks 时,类型 A 为 number
+// 不打开时,类型 A 为 string
+type A = unknown extends {} ? string : number;
+```
+
+上面示例中,`{}`代表了 Object 类型,不打开`strictNullChecks`时,它包括了`undefined`和`null`,就相当于包括了所有类型的值,所以这时`unknown`类型可以赋值给`{}`类型,类型`A`就为`number`。打开`strictNullChecks`时,`{}`就排除掉了`undefined`和`null`,这时`unknown`类型就不能赋值给`{}`类型后,类型`A`就为`string`。
+
+另外,`strict`属性包含了`strictNullChecks`,如果打开`strict`属性,就相当于打开了`strictNullChecks`。
+
 ### strictPropertyInitialization
 
 `strictPropertyInitialization`设置类的实例属性都必须初始化,包括以下几种情况。

From 5361b8c9484da37e647681935236356f4b3a9509 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Thu, 3 Oct 2024 22:44:55 +0800
Subject: [PATCH 117/120] docs(declare): edit text

---
 docs/declare.md       | 12 ++++++++++++
 docs/tsconfig.json.md |  4 +++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/docs/declare.md b/docs/declare.md
index ca7665a..a9b4bd0 100644
--- a/docs/declare.md
+++ b/docs/declare.md
@@ -252,6 +252,7 @@ const a:A = { x: 0, y: 0 };
 某些第三方模块,原始作者没有提供接口类型,这时可以在自己的脚本顶部加上下面一行命令。
 
 ```typescript
+// 语法
 declare module "模块名";
 
 // 例子
@@ -371,6 +372,17 @@ declare module "path" {
 
 上面示例中,`url`和`path`都是单独的模块脚本,但是它们的类型都定义在`node.d.ts`这个文件里面。
 
+另一种情况是,使用`declare module`命令,为模块名指定加载路径。
+
+```typescript
+declare module "lodash" {
+  export * from "../../dependencies/lodash";
+  export default from "../../dependencies/lodash";
+}
+```
+
+上面示例中,`declare module "lodash"`为模块`lodash`,指定具体的加载路径。
+
 使用时,自己的脚本使用三斜杠命令,加载这个类型声明文件。
 
 ```typescript
diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index a6b82db..4312c11 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -536,7 +536,9 @@ TypeScript 内置的类型描述文件,主要有以下一些,完整的清单
 }
 ```
 
-它还可以使用通配符“*”。
+上面示例中,paths 设置的是执行`require('b')`时,即加载的是`./bar/b`。
+
+它还可以使用通配符“*”,表明模块名与模块位置的对应关系。
 
 ```typescript
 {

From 635a5fadebf813bdc3feb582c310eccc46e1739c Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Sat, 12 Oct 2024 10:51:00 +0800
Subject: [PATCH 118/120] docs(tsconfig.json): fixed #124

---
 docs/tsconfig.json.md | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/docs/tsconfig.json.md b/docs/tsconfig.json.md
index 4312c11..e94a7c2 100644
--- a/docs/tsconfig.json.md
+++ b/docs/tsconfig.json.md
@@ -679,7 +679,7 @@ let func:StringOrNumberFunc = fn;
 
 ### strictNullChecks
 
-不打开`strictNullChecks`的情况下,变量可以设为`undefined`或`null`,而不管其类型是什么。
+不打开`strictNullChecks`的情况下,一个变量不管类型是什么,都可以赋值为`undefined`或`null`。
 
 ```typescript
 // 不打开 strictNullChecks 的情况
@@ -689,9 +689,9 @@ x = undefined; // 不报错
 x = null; // 不报错
 ```
 
-上面示例中,变量`x`的类型是`number`,但是赋值为`undefined`或`null`都不会报错。这是为了继承 JavaScript 的设定:当变量没有赋值时,它的值就为`undefined`。
+上面示例中,不打开`strictNullChecks`时,变量`x`的类型是`number`,但是赋值为`undefined`或`null`都不会报错。这是为了继承 JavaScript 的设定:当变量没有赋值时,它的值就为`undefined`。
 
-一旦打开`strictNullChecks`,就相当于从变量的值里面,排除了`undefined`和`null`,除非变量的类型是这两种类型。
+一旦打开`strictNullChecks`,就使用严格类型,禁止变量赋值为`undefined`和`null`,除非变量原本就是这两种类型。它相当于从变量的值里面,排除了`undefined`和`null`。
 
 ```typescript
 // 打开 strictNullChecks 的情况
@@ -701,6 +701,8 @@ x = undefined; // 报错
 x = null; // 报错
 ```
 
+上面示例中,打开`strictNullChecks`时,变量`x`作为`number`类型,就不能赋值为`undefined`和`null`。
+
 下面是一个例子。
 
 ```typescript
@@ -709,9 +711,9 @@ x = null; // 报错
 type A = unknown extends {} ? string : number;
 ```
 
-上面示例中,`{}`代表了 Object 类型,不打开`strictNullChecks`时,它包括了`undefined`和`null`,就相当于包括了所有类型的值,所以这时`unknown`类型可以赋值给`{}`类型,类型`A`就为`number`。打开`strictNullChecks`时,`{}`就排除掉了`undefined`和`null`,这时`unknown`类型就不能赋值给`{}`类型后,类型`A`就为`string`。
+上面示例中,`{}`代表了 Object 类型,不打开`strictNullChecks`时,它包括了`undefined`和`null`,就相当于包括了所有类型的值,所以这时`unknown`类型可以赋值给`{}`类型,类型`A`就为`string`。打开`strictNullChecks`时,`{}`就排除掉了`undefined`和`null`,这时`unknown`类型就不能赋值给`{}`类型后,类型`A`就为`number`。
 
-另外,`strict`属性包含了`strictNullChecks`,如果打开`strict`属性,就相当于打开了`strictNullChecks`。
+最后,`strict`属性包含了`strictNullChecks`,如果打开`strict`属性,就相当于打开了`strictNullChecks`。
 
 ### strictPropertyInitialization
 

From 1725cbbcd1cfbd9bf7110fd6ead3edb5ff9ed180 Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 15 Oct 2024 19:08:17 +0800
Subject: [PATCH 119/120] docs(operator/extends): fixed #125

---
 docs/operator.md | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/docs/operator.md b/docs/operator.md
index 5416439..7a51d4b 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -378,18 +378,17 @@ type T2 = RegExp extends Animal ? number : string;
 
 一般来说,调换`extends`两侧类型,会返回相反的结果。举例来说,有两个类`Cat`和`Animal`,前者是后者的子类型,那么`Cat extends Animal`就为真,而`Animal extends Cat`就为伪。
 
-如果需要判断的类型是一个联合类型,那么条件运算符会展开这个联合类型。
+如果对泛型使用 extends 条件运算,有一个地方需要注意。当泛型的类型参数是一个联合类型时,那么条件运算符会展开这个类型参数,即`T<A|B> = T<A> | T<B>`,所以 extends 对类型参数的每个部分是分别计算的。
 
 ```typescript
-(A|B) extends U ? X : Y
+type Cond<T> = T extends U ? X : Y;
 
-// 等同于
-
-(A extends U ? X : Y) |
-(B extends U ? X : Y)
+type MyType = Cond<A|B>;
+// 等同于 Cond<A> | Cond<B>
+// 等同于 (A extends U ? X : Y) | (B extends U ? X : Y)
 ```
 
-上面示例中,`A|B`是一个联合类型,进行条件运算时,相当于`A`和`B`分别进行运算符,返回结果组成一个联合类型。
+上面示例中,泛型`Cond`的类型参数`A|B`是一个联合类型,进行条件运算时,相当于`A`和`B`分别进行条件运算,返回结果组成一个联合类型。也就是说,如果类型参数是联合类型,条件运算的返回结果依然是一个联合类型。
 
 如果不希望联合类型被条件运算符展开,可以把`extends`两侧的操作数都放在方括号里面。
 
@@ -398,18 +397,18 @@ type T2 = RegExp extends Animal ? number : string;
 type ToArray<Type> =
   Type extends any ? Type[] : never;
 
-// string[]|number[]
+// 返回结果 string[]|number[]
 type T = ToArray<string|number>;
 
 // 示例二
 type ToArray<Type> =
   [Type] extends [any] ? Type[] : never;
 
-// (string | number)[]
+// 返回结果 (string | number)[]
 type T = ToArray<string|number>;
 ```
 
-上面的示例一,传入`ToArray<Type>`的类型参数是一个联合类型,所以会被展开,返回的也是联合类型。示例二是`extends`两侧的运算数都放在方括号里面,所以传入的联合类型不会展开,返回的是一个数组。
+上面的示例一,泛型`ToArray<Type>`的类型参数`string|number`是一个联合类型,所以会被展开,返回的也是联合类型`string[]|number[]`。示例二是`extends`两侧的运算数都放在方括号里面,左侧是`[Type]`,右侧是`[any]`,这时传入的联合类型不会展开,返回的是一个数组`(string|number)[]`。
 
 条件运算符还可以嵌套使用。
 

From 1f5e92981ab36601ee9b473642ba59f434a73e9d Mon Sep 17 00:00:00 2001
From: ruanyf <yifeng.ruan@gmail.com>
Date: Tue, 31 Dec 2024 09:56:43 +0800
Subject: [PATCH 120/120] docs(operator): fixed typo

---
 docs/operator.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/operator.md b/docs/operator.md
index 7a51d4b..b19ec56 100644
--- a/docs/operator.md
+++ b/docs/operator.md
@@ -660,7 +660,7 @@ const palette: Record<Colors, string|RGB> = {
 const greenComponent = palette.green.substring(1, 6); // 报错
 ```
 
-上面示例中,`palette.green`属性调用`substring()`方法会报错,原因是这个方法只有字符串才有,而`palette.green`的类型是`srting|RGB`,除了字符串,还可能是元组`RGB`,而元组并不存在`substring()`方法,所以报错了。
+上面示例中,`palette.green`属性调用`substring()`方法会报错,原因是这个方法只有字符串才有,而`palette.green`的类型是`string|RGB`,除了字符串,还可能是元组`RGB`,而元组并不存在`substring()`方法,所以报错了。
 
 如果要避免报错,要么精确给出变量`palette`每个属性的类型,要么对`palette.green`的值进行类型缩小。两种做法都比较麻烦,也不是很有必要。