From 0af98cf1df5183f953a187d9ad6a9c4e99978d4d Mon Sep 17 00:00:00 2001 From: hanyujie2002 Date: Tue, 23 Jan 2024 16:53:51 +0800 Subject: [PATCH] fix some typesetting (#45) * fix some typesetting * fix --- docs/documentation/zh/handbook-v2/Basics.md | 2 +- .../zh/handbook-v2/Everyday Types.md | 86 +++++++++---------- docs/documentation/zh/handbook-v2/Modules.md | 14 +-- .../zh/handbook-v2/More on Functions.md | 56 ++++++------ .../documentation/zh/handbook-v2/Narrowing.md | 35 ++++---- .../zh/handbook-v2/Object Types.md | 24 +++--- .../zh/handbook-v2/The Handbook.md | 6 +- .../Type Manipulation/Conditional Types.md | 10 +-- .../handbook-v2/Type Manipulation/Generics.md | 8 +- .../Type Manipulation/Indexed Access Types.md | 4 +- .../Template Literal Types.md | 2 +- .../Type Manipulation/Typeof Type Operator.md | 8 +- .../_Creating Types from Types.md | 6 +- 13 files changed, 131 insertions(+), 130 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Basics.md b/docs/documentation/zh/handbook-v2/Basics.md index ac6070a..8a39d30 100644 --- a/docs/documentation/zh/handbook-v2/Basics.md +++ b/docs/documentation/zh/handbook-v2/Basics.md @@ -2,7 +2,7 @@ title: 基础 layout: docs permalink: /zh/docs/handbook/2/basic-types.html -oneline: "学习 TypeScript 的第一步:基本类型。" +oneline: "学习 TypeScript 的第一步:基本类型" preamble: >

欢迎来到手册的第一页。如果这是你第一次接触到 TypeScript,你可能需要先阅读一下'入门'指南

--- diff --git a/docs/documentation/zh/handbook-v2/Everyday Types.md b/docs/documentation/zh/handbook-v2/Everyday Types.md index 6434f1c..3e8c0fa 100644 --- a/docs/documentation/zh/handbook-v2/Everyday Types.md +++ b/docs/documentation/zh/handbook-v2/Everyday Types.md @@ -2,12 +2,12 @@ title: 常见类型 layout: docs permalink: /zh/docs/handbook/2/everyday-types.html -oneline: "语言基本类型。" +oneline: "语言基本类型" --- 在本章中,我们将介绍一些在 JavaScript 代码中最常见的值的类型,并说明在 TypeScript 中描述这些类型相应的方法。这不是一个详尽的列表,后续章节将描述命名和使用其他类型的更多方法。 -类型还可以出现在许多 _地方_ ,而不仅仅是类型注释。在我们了解类型本身的同时,我们还将了解在哪些地方可以引用这些类型来形成新的结构。 +类型还可以出现在许多*地方*,而不仅仅是类型注释。在我们了解类型本身的同时,我们还将了解在哪些地方可以引用这些类型来形成新的结构。 我们将首先回顾一下你在编写 JavaScript 或 TypeScript 代码时可能遇到的最基本和最常见的类型。这些将在稍后形成更复杂类型的核心构建块。 @@ -23,9 +23,9 @@ JavaScript 有三种非常常用的[基本类型](https://developer.mozilla.org/ ## 数组 -要指定类似 `[1, 2, 3]` 的数组的类型,可以使用语法 `number[]`;这个语法适用于任何类型(例如 `string[]` 是字符串数组,依此类推)。你可能还会看到其写作 `Array`,它们的意思是一样的。当我们学习_泛型_时,将更多地了解到 `T` 语法的含义。 +要指定类似 `[1, 2, 3]` 的数组的类型,可以使用语法 `number[]`;这个语法适用于任何类型(例如 `string[]` 是字符串数组,依此类推)。你可能还会看到其写作 `Array`,它们的意思是一样的。当我们学习*泛型*时,将更多地了解到 `T` 语法的含义。 -> 请注意,`[number]` 是不同的东西;请参阅关于_元组类型_的部分。 +> 请注意,`[number]` 是不同的东西;请参阅关于*元组类型*的部分。 ## `any` @@ -62,12 +62,12 @@ let myName: string = "Alice"; ``` > TypeScript 不使用类似 `int x = 0;` 的“左侧类型”声明。 -> 类型注解总是放在被注解的内容_之后_。 +> 类型注解总是放在被注解的内容*之后*。 但在大多数情况下,并不是必须要这样。TypeScript 会尽可能自动根据代码推断出类型。例如,以下变量的类型是根据其初始化的值推断出来的: ```ts twoslash -// 不需要类型注解——“myName” 推断为 “string” 类型 +// 不需要类型注解——“myName”推断为 “string” 类型 let myName = "Alice"; ``` @@ -138,11 +138,11 @@ names.forEach((s) => { 尽管参数 `s` 没有类型注解,但 TypeScript 使用了 `forEach` 函数的类型以及数组的推断类型,来确定 `s` 的类型。 -这个过程被称为_上下文类型推断_,因为函数出现的_上下文_告诉它应该具有的类型。类似于推断规则,你不需要显式地学习这个过程是如何发生的,但了解它发生的事实可以帮助你注意到不需要类型注解的情况。稍后,我们将看到更多关于值所处的上下文如何影响其类型的示例。 +这个过程被称为*上下文类型推断*,因为函数出现的*上下文*告诉它应该具有的类型。类似于推断规则,你不需要显式地学习这个过程是如何发生的,但了解它发生的事实可以帮助你注意到不需要类型注解的情况。稍后,我们将看到更多关于值所处的上下文如何影响其类型的示例。 ## 对象类型 -除了基本类型之外,最常见的类型是_对象类型_。任何具有属性的 JavaScript 值都是对象类型,其几乎包括所有值!要定义一个对象类型,我们只需要列出其属性及其属性的类型。 +除了基本类型之外,最常见的类型是*对象类型*。任何具有属性的 JavaScript 值都是对象类型,其几乎包括所有值!要定义一个对象类型,我们只需要列出其属性及其属性的类型。 例如,这是一个以类似于点的对象为参数的函数: @@ -162,7 +162,7 @@ printCoord({ x: 3, y: 7 }); ### 可选属性 -对象类型还可以指定它们的某些或所有属性是_可选的_。要实现这一点,可以在属性名后面加上 `?`: +对象类型还可以指定它们的某些或所有属性是*可选的*。要实现这一点,可以在属性名后面加上 `?`: ```ts twoslash function printName(obj: { first: string; last?: string }) { @@ -173,7 +173,7 @@ printName({ first: "Bob" }); printName({ first: "Alice", last: "Alisson" }); ``` -在 JavaScript 中,如果访问一个不存在的属性,你会得到 `undefined` 而不是运行时错误。因此,如果你_读取_的是一个可选属性的话,那么在使用它之前,你需要检查其是否为 `undefined`。 +在 JavaScript 中,如果访问一个不存在的属性,你会得到 `undefined` 而不是运行时错误。因此,如果你*读取*的是一个可选属性的话,那么在使用它之前,你需要检查其是否为 `undefined`。 ```ts twoslash // @errors: 2532 @@ -192,11 +192,11 @@ function printName(obj: { first: string; last?: string }) { ## 联合类型 -TypeScript 的类型系统允许你使用各种运算符从现有类型构建新类型。现在我们了解了如何编写一些类型,是时候开始以有趣的方式_组合(combine)_它们了。 +TypeScript 的类型系统允许你使用各种运算符从现有类型构建新类型。现在我们了解了如何编写一些类型,是时候开始以有趣的方式*组合(combine)*它们了。 ### 定义联合类型 -_联合_(Union)类型是组合类型的一种方式。联合类型是由两个或更多其他类型形成的类型,表示值可以是这些类型中的_任意一个_。我们将每个类型都称为联合的_成员_。 +*联合*(Union)类型是组合类型的一种方式。联合类型是由两个或更多其他类型形成的类型,表示值可以是这些类型中的*任意一个*。我们将每个类型都称为联合的*成员*。 以下是可以操作字符串或数字的函数: @@ -215,7 +215,7 @@ printId({ myID: 22342 }); ### 使用联合类型 -提供与联合类型匹配的值很容易——只需提供与联合的成员之一匹配的类型即可。但是如果你_有_一个联合类型的值,你该如何使用它呢? +提供与联合类型匹配的值很容易——只需提供与联合的成员之一匹配的类型即可。但是如果你*有*一个联合类型的值,你该如何使用它呢? 只有当某个操作对联合的每个成员都有效时,TypeScript 才允许你对联合类型值进行操作。例如,如果你有一个 `string | number` 的联合类型,那么你不能使用仅适用于 `string` 的方法: @@ -226,7 +226,7 @@ function printId(id: number | string) { } ``` -解决方法是使用代码来_紧缩_联合类型的范围,就像在没有类型注解的 JavaScript 中一样。如果 TypeScript 可以根据代码的结构推断出更具体的类型的值的话,就会发生_紧缩_。 +解决方法是使用代码来*紧缩*联合类型的范围,就像在没有类型注解的 JavaScript 中一样。如果 TypeScript 可以根据代码的结构推断出更具体的类型的值的话,就会发生*紧缩*。 例如,TypeScript 知道只有 `string` 的 `typeof` 值为 `"string"`: @@ -267,17 +267,17 @@ function getFirstThree(x: number[] | string) { } ``` -> _联合_类型的名字可能会让人困惑,因为它实际上是这些类型的属性的_交集_。(译注:联合类型的英文是“Union”,和并集是同一个单词) -> 这是有意为之(名称_联合类型_来自于类型理论)。 -> 联合类型 `number | string` 是通过将每个类型的_值_合并而组成的。 -> 注意,给定两个集合,每个集合有相应特征,只有这些特征的_交集_适用于这些集合的_合集_。 -> 例如,假设有一个房间,里面的人都是戴帽子的高个,而另一个房间里的人都戴帽子且说西班牙语,将这些房间组合在一起后,我们只知道_每个_人都戴着帽子。 +> *联合*类型的名字可能会让人困惑,因为它实际上是这些类型的属性的*交集*。(译注:联合类型的英文是“Union”,和并集是同一个单词) +> 这是有意为之(名称*联合类型*来自于类型理论)。 +> 联合类型 `number | string` 是通过将每个类型的*值*合并而组成的。 +> 注意,给定两个集合,每个集合有相应特征,只有这些特征的*交集*适用于这些集合的*合集*。 +> 例如,假设有一个房间,里面的人都是戴帽子的高个,而另一个房间里的人都戴帽子且说西班牙语,将这些房间组合在一起后,我们只知道*每个*人都戴着帽子。 ## 类型别名 可以直接在类型注解中编写对象类型和联合类型来使用它们。这虽然很方便,但是我们常常会有一个需求,就是如果多次使用同一个类型的话,可以通过一个名称来引用它。 -_类型别名_正是如此(任意_类型_的_名称_)。类型别名的语法是: +*类型别名*正是如此(任意*类型*的*名称*)。类型别名的语法是: ```ts twoslash type Point = { @@ -300,12 +300,12 @@ printCoord({ x: 100, y: 100 }); type ID = number | string; ``` -请注意,别名_只是_别名(你不能使用类型别名来创建同一类型的不同“版本”)。当你使用别名时,它与你编写的别名所对应的类型完全一样。换句话说,这段代码可能_看起来_是非法的,但是对于 TypeScript 来说是正确的,因为这两种类型都是同一类型的别名: +请注意,别名*只是*别名(你不能使用类型别名来创建同一类型的不同“版本”)。当你使用别名时,它与你编写的别名所对应的类型完全一样。换句话说,这段代码可能*看起来*是非法的,但是对于 TypeScript 来说是正确的,因为这两种类型都是同一类型的别名: ```ts twoslash declare function getInput(): string; declare function sanitize(str: string): string; -// ---分割--- +// ---cut--- type UserInputSanitizedString = string; function sanitizeInput(str: string): UserInputSanitizedString { @@ -321,7 +321,7 @@ userInput = "新的输入"; ## 接口 -_接口声明_是命名对象类型的另一种方式: +*接口声明*是命名对象类型的另一种方式: ```ts twoslash interface Point { @@ -337,7 +337,7 @@ function printCoord(pt: Point) { printCoord({ x: 100, y: 100 }); ``` -就像我们上面使用类型别名时一样,这个示例的工作方式就像我们使用了匿名对象类型一样。TypeScript 只关心我们传递给 `printCoord` 的值的结构——它只关心它是否具有预期的属性。只关心类型的结构和功能,这就是为什么我们说 TypeScript 是一个_结构化类型_的类型系统。 +就像我们上面使用类型别名时一样,这个示例的工作方式就像我们使用了匿名对象类型一样。TypeScript 只关心我们传递给 `printCoord` 的值的结构——它只关心它是否具有预期的属性。只关心类型的结构和功能,这就是为什么我们说 TypeScript 是一个*结构化类型*的类型系统。 ### 类型别名和接口之间的区别 @@ -411,10 +411,10 @@ type Window = { 在后面的章节中你会学到更多关于这些概念的知识,所以如果你没有立即理解这些知识,请不要担心。 -- 在 TypeScript 4.2 之前,类型别名命名 [_可能_ 会出现在错误消息中](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA),有时代替等效的匿名类型(可能需要也可能不需要)。接口在错误消息中将始终被命名。 -- 类型别名不能参与 [声明合并,但接口可以](/play?#code/PTAEEEDtQS0gXApgJwGYEMDGjSfdAIx2UQFoB7AB0UkQBMAoEUfO0Wgd1ADd0AbAK6IAzizp16ALgYM4SNFhwBZdAFtV-UAG8GoPaADmNAcMmhh8ZHAMMAvjLkoM2UCvWad+0ARL0A-GYWVpA29gyY5JAWLJAwGnxmbvGgALzauvpGkCZmAEQAjABMAMwALLkANBl6zABi6DB8okR4Jjg+iPSgABboovDk3jjo5pbW1d6+dGb5djLwAJ7UoABKiJTwjThpnpnGpqPBoTLMAJrkArj4kOTwYmycPOhW6AR8IrDQ8N04wmo4HHQCwYi2Waw2W1S6S8HX8gTGITsQA)。 -- 接口只能用于 [声明对象的形状,不能重命名基本类型](/play?#code/PTAEAkFMCdIcgM6gC4HcD2pIA8CGBbABwBtIl0AzUAKBFAFcEBLAOwHMUBPQs0XFgCahWyGBVwBjMrTDJMAshOhMARpD4tQ6FQCtIE5DWoixk9QEEWAeV37kARlABvaqDegAbrmL1IALlAEZGV2agBfampkbgtrWwMAJlAAXmdXdy8ff0Dg1jZwyLoAVWZ2Lh5QVHUJflAlSFxROsY5fFAWAmk6CnRoLGwmILzQQmV8JmQmDzI-SOiKgGV+CaYAL0gBBdyy1KCQ-Pn1AFFplgA5enw1PtSWS+vCsAAVAAtB4QQWOEMKBuYVUiVCYvYQsUTQcRSBDGMGmKSgAAa-VEgiQe2GLgKQA). -- 接口名称将 [_始终_ 以其原始形式出现](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWY2Q-YAjABMAMwALA+gbsVjNXW8yxySoAADaAA0CCaZbPh1XYqXgOIY0ZgmcK0AA0nyaLFhhGY8F4AHJmEJILCWsgZId4NNfIgGFdcIcUTVfgBlZTOWC8T7kAJ42G4eT+GS42QyRaYbCgXAEEguTzeXyCjDBSAAQSE8Ai0Xsl0K9kcziExDeiQs1lAqSE6SyOTy0AKQ2KHk4p1V6s1OuuoHuzwArMagA) 在错误消息中,但 _只有_ 在按名称使用时才会出现。 +- 在 TypeScript 4.2 之前,类型别名命名[*可能* 会出现在错误消息中](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA),有时代替等效的匿名类型(可能需要也可能不需要)。接口在错误消息中将始终被命名。 +- 类型别名不能参与[声明合并,但接口可以](/play?#code/PTAEEEDtQS0gXApgJwGYEMDGjSfdAIx2UQFoB7AB0UkQBMAoEUfO0Wgd1ADd0AbAK6IAzizp16ALgYM4SNFhwBZdAFtV-UAG8GoPaADmNAcMmhh8ZHAMMAvjLkoM2UCvWad+0ARL0A-GYWVpA29gyY5JAWLJAwGnxmbvGgALzauvpGkCZmAEQAjABMAMwALLkANBl6zABi6DB8okR4Jjg+iPSgABboovDk3jjo5pbW1d6+dGb5djLwAJ7UoABKiJTwjThpnpnGpqPBoTLMAJrkArj4kOTwYmycPOhW6AR8IrDQ8N04wmo4HHQCwYi2Waw2W1S6S8HX8gTGITsQA)。 +- 接口只能用于[声明对象的形状,不能重命名基本类型](/play?#code/PTAEAkFMCdIcgM6gC4HcD2pIA8CGBbABwBtIl0AzUAKBFAFcEBLAOwHMUBPQs0XFgCahWyGBVwBjMrTDJMAshOhMARpD4tQ6FQCtIE5DWoixk9QEEWAeV37kARlABvaqDegAbrmL1IALlAEZGV2agBfampkbgtrWwMAJlAAXmdXdy8ff0Dg1jZwyLoAVWZ2Lh5QVHUJflAlSFxROsY5fFAWAmk6CnRoLGwmILzQQmV8JmQmDzI-SOiKgGV+CaYAL0gBBdyy1KCQ-Pn1AFFplgA5enw1PtSWS+vCsAAVAAtB4QQWOEMKBuYVUiVCYvYQsUTQcRSBDGMGmKSgAAa-VEgiQe2GLgKQA)。 +- 接口名称将[*始终*以其原始形式出现](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWY2Q-YAjABMAMwALA+gbsVjNXW8yxySoAADaAA0CCaZbPh1XYqXgOIY0ZgmcK0AA0nyaLFhhGY8F4AHJmEJILCWsgZId4NNfIgGFdcIcUTVfgBlZTOWC8T7kAJ42G4eT+GS42QyRaYbCgXAEEguTzeXyCjDBSAAQSE8Ai0Xsl0K9kcziExDeiQs1lAqSE6SyOTy0AKQ2KHk4p1V6s1OuuoHuzwArMagA)在错误消息中,但*只有*在按名称使用时才会出现。 在大多数情况下,你可以根据个人喜好进行选择,TypeScript 会告诉你它是否需要其他类型的声明。如果你想要启发式方法,可以使用 `interface` 直到你需要使用 `type` 中的功能。 @@ -422,9 +422,9 @@ type Window = { 有时候你会遇到一种情况,就是 TypeScript 无法确定一些类型。 -例如,如果你使用 `document.getElementById`,TypeScript 只能知道它返回_某种_`HTMLElement`,但是可能你希望 TypeScript 知道的更具体一点,例如让它知道这个 ID 指向的应当是一个 `HTMLCanvasElement`。 +例如,如果你使用 `document.getElementById`,TypeScript 只能知道它返回*某种* `HTMLElement`,但是可能你希望 TypeScript 知道的更具体一点,例如让它知道这个 ID 指向的应当是一个 `HTMLCanvasElement`。 -在这种情况下,你可以使用_类型断言_来指定更具体的类型: +在这种情况下,你可以使用*类型断言*来指定更具体的类型: ```ts twoslash const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; @@ -441,7 +441,7 @@ const myCanvas = document.getElementById("main_canvas"); > 提醒:由于类型断言在编译时被移除,因此没有与类型断言相关的运行时检查。 > 如果类型断言错误,不会生成异常或 `null`。 -TypeScript 只允许将类型断言为_更具体_或_更不具体_的类型。这个规则阻止了一些“不可能”的强制转换,比如: +TypeScript 只允许将类型断言为*更具体*或*更不具体*的类型。这个规则阻止了一些“不可能”的强制转换,比如: ```ts twoslash // @errors: 2352 @@ -459,7 +459,7 @@ const a = expr as any as T; ## 字面类型(literal type) -除了通用的 `string` 和 `number` 类型之外,我们还可以在类型位置引用_特定的_字符串和数字。 +除了通用的 `string` 和 `number` 类型之外,我们还可以在类型位置引用*特定的*字符串和数字。 可以这样想,JavaScript 提供了不同的声明变量的方式。`var` 和 `let` 都允许改变变量中保存的值,而 `const` 则不允许。这体现在 TypeScript 创建字面类型的方式上。 @@ -489,7 +489,7 @@ x = "howdy"; 只能是固定一个值的变量并没有多大用处! -但是如果将字面类型_组合_成联合类型,就可以表达更有用的概念,例如,只接受一组特定已知值的函数: +但是如果将字面类型*组合*成联合类型,就可以表达更有用的概念,例如,只接受一组特定已知值的函数: ```ts twoslash // @errors: 2345 @@ -538,7 +538,7 @@ if (someCondition) { } ``` -TypeScript 不会认为将 `1` 赋值给之前为 `0` 的字段是一个错误。换句话说,`obj.counter` 必须具有类型 `number`,而不是 `0`,因为类型用于确定_读取_和_写入_行为。 +TypeScript 不会认为将 `1` 赋值给之前为 `0` 的字段是一个错误。换句话说,`obj.counter` 必须具有类型 `number`,而不是 `0`,因为类型用于确定*读取*和*写入*行为。 字符串也是同样的情况: @@ -556,7 +556,7 @@ handleRequest(req.url, req.method); 1. 可以通过在任一位置添加类型断言来改变推断结果: - ````ts twoslash + ```ts twoslash declare function handleRequest(url: string, method: "GET" | "POST"): void; // ---cut--- // 改变 1: @@ -570,28 +570,28 @@ handleRequest(req.url, req.method); 2. 可以使用 `as const` 将整个对象转换为字面量类型: - ````ts twoslash + ```ts twoslash declare function handleRequest(url: string, method: "GET" | "POST"): void; // ---cut--- const req = { url: "https://example.com", method: "GET" } as const; handleRequest(req.url, req.method); ``` - ``as const` 后缀的作用类似于 `const`,但是针对的是类型系统,确保所有属性都被赋予字面量类型,而不是更一般的类型,如 `string` 或 `number`。 + `as const` 后缀的作用类似于 `const`,但是针对的是类型系统,确保所有属性都被赋予字面量类型,而不是更一般的类型,如 `string` 或 `number`。 ## `null` 和 `undefined` JavaScript 有两个基本值,用于表示缺失或未初始化的值:`null` 和 `undefined`。 -TypeScript 也有两个相应的_类型_,名称相同。这些类型的特性取决于是否打开了 `strictNullChecks` 选项。 +TypeScript 也有两个相应的*类型*,名称相同。这些类型的特性取决于是否打开了 `strictNullChecks` 选项。 ### `strictNullChecks` 关闭 -如果 `strictNullChecks` _关闭_,可能为 `null` 或 `undefined` 的值仍然可以正常访问,并且可以将 `null` 和 `undefined` 赋值给任何类型的属性。这类似于没有空值检查的语言(例如 C#、Java)的行为。不检查这些值的缺失往往是错误的主要来源;建议尽可能打开 `strictNullChecks`。 +如果 `strictNullChecks` *关闭*,可能为 `null` 或 `undefined` 的值仍然可以正常访问,并且可以将 `null` 和 `undefined` 赋值给任何类型的属性。这类似于没有空值检查的语言(例如 C#、Java)的行为。不检查这些值的缺失往往是错误的主要来源;建议尽可能打开 `strictNullChecks`。 ### `strictNullChecks` 打开 -如果 `strictNullChecks` _打开_,当一个值为 `null` 或 `undefined` 时,你需要在使用该值的方法或属性之前进行检查。就像在使用可选属性之前检查 `undefined` 一样,我们可以使用_缩小类型_来检查可能为 `null` 的值: +如果 `strictNullChecks` *打开*,当一个值为 `null` 或 `undefined` 时,你需要在使用该值的方法或属性之前进行检查。就像在使用可选属性之前检查 `undefined` 一样,我们可以使用*缩小类型*来检查可能为 `null` 的值: ```ts twoslash function doSomething(x: string | null) { @@ -614,11 +614,11 @@ function liveDangerously(x?: number | null) { } ``` -与其他类型断言一样,这不会改变你的代码的运行行为,因此只有在你知道该值_不可能_为 `null` 或 `undefined` 时才使用 `!`。 +与其他类型断言一样,这不会改变你的代码的运行行为,因此只有在你知道该值*不可能*为 `null` 或 `undefined` 时才使用 `!`。 ## 枚举 -枚举是 TypeScript 添加到 JavaScript 中的功能,它允许描述一个值,该值可以是一组可能的命名常量之一。与大多数 TypeScript 特性不同,这_不是_ JavaScript 类型级别的添加,而是添加到语言和运行时的功能。因此,你应该知道这个特性的存在,但除非你确定,否则最好不要使用。你可以在[枚举参考页面](https://www.typescriptlang.org/docs/handbook/enums.html)上阅读更多关于枚举的信息。 +枚举是 TypeScript 添加到 JavaScript 中的功能,它允许描述一个值,该值可以是一组可能的命名常量之一。与大多数 TypeScript 特性不同,这*不是* JavaScript 类型级别的添加,而是添加到语言和运行时的功能。因此,你应该知道这个特性的存在,但除非你确定,否则最好不要使用。你可以在[枚举参考页面](https://www.typescriptlang.org/docs/handbook/enums.html)上阅读更多关于枚举的信息。 ## 不常见的原始类型 @@ -638,7 +638,7 @@ const oneHundred: bigint = BigInt(100); const anotherHundred: bigint = 100n; ``` -你可以在 [TypeScript 3.2 发布说明](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html#bigint)中了解更多关于 `BigInt` 的信息。 +你可以在 [TypeScript 3.2 发布说明](/docs/handbook/release-notes/typescript-3-2.html#bigint)中了解更多关于 `BigInt` 的信息。 ##### `symbol` diff --git a/docs/documentation/zh/handbook-v2/Modules.md b/docs/documentation/zh/handbook-v2/Modules.md index aca9929..90a4685 100644 --- a/docs/documentation/zh/handbook-v2/Modules.md +++ b/docs/documentation/zh/handbook-v2/Modules.md @@ -2,14 +2,14 @@ title: 模块 layout: docs permalink: /zh/docs/handbook/2/modules.html -oneline: "JavaScript 处理跨文件通信的方式。" +oneline: "JavaScript 处理跨文件通信的方式" --- JavaScript 历来具有多种处理代码模块化的方式。TypeScript 自 2012 年问世以来,已经实现了对这其中很多格式的支持。但随着时间的推移,社区和 JavaScript 规范已经趋于使用一种称为 ES 模块(或 ES6 模块)的格式。它使用的是 `import`/`export` 语法。 ES 模块在 2015 年被添加到 JavaScript 规范中,并且截至 2020 年已经在大多数 Web 浏览器和 JavaScript 运行时中得到广泛支持。 -本手册将重点介绍 ES 模块及其流行的前身 CommonJS `module.exports =` 语法,你可以在参考部分的 [模块](/docs/handbook/modules.html) 下找到其他模块模式的信息。 +本手册将重点介绍 ES 模块及其流行的前身 CommonJS `module.exports =` 语法,你可以在参考部分的[模块](/docs/handbook/modules.html)下找到其他模块模式的信息。 ## JavaScript 模块的定义方式 @@ -198,7 +198,7 @@ TypeScript 通过两个用来声明类型导入的概念,扩展了 `import` ###### `import type` -这是一个_仅_能导入类型的导入语句: +这是一个*仅*能导入类型的导入语句: ```ts twoslash // @filename: animal.ts @@ -237,7 +237,7 @@ const name = createCatName(); #### 具有 CommonJS 行为的 ES 模块语法 -TypeScript 具有 ES 模块语法,它与 CommonJS 和 AMD 的 `require` _直接_对应。使用 ES 模块进行导入在大多数情况下与这些环境中的 `require` 相同,但是此语法确保你的 TypeScript 文件与 CommonJS 输出保持一对一的匹配: +TypeScript 具有 ES 模块语法,它与 CommonJS 和 AMD 的 `require` *直接*对应。使用 ES 模块进行导入在大多数情况下与这些环境中的 `require` 相同,但是此语法确保你的 TypeScript 文件与 CommonJS 输出保持一对一的匹配: ```ts twoslash /// @@ -247,7 +247,7 @@ import fs = require("fs"); const code = fs.readFileSync("hello.ts", "utf8"); ``` -你可以在 [模块参考页面](/docs/handbook/modules.html#export--and-import--require) 了解更多关于此语法的信息。 +你可以在[模块参考页面](/docs/handbook/modules.html#export--and-import--require)了解更多关于此语法的信息。 ## CommonJS 语法 @@ -333,7 +333,7 @@ TypeScript 包括两种解析策略:经典解析和 Node 解析。经典解析 有许多 TSConfig 标志会影响 TypeScript 内部的模块策略,包括 [`moduleResolution`](/tsconfig#moduleResolution)、[`baseUrl`](/tsconfig#baseUrl)、[`paths`](/tsconfig#paths) 和 [`rootDirs`](/tsconfig#rootDirs)。 -要了解这些策略的详细信息,可以参考 [模块解析](/docs/handbook/module-resolution.html)。 +要了解这些策略的详细信息,可以参考[模块解析](/docs/handbook/module-resolution.html)。 ## TypeScript 的模块输出选项 @@ -393,7 +393,7 @@ export const twoPi = valueOfPi * 2; > 请注意,ES2020 在功能上与原始的 `index.ts` 相同。 -你可以在 [TSConfig 的 `module` 配置参考页面](/tsconfig#module) 中查看所有可用选项及其生成的 JavaScript 代码。 +你可以在 [TSConfig 的 `module` 配置参考页面](/tsconfig#module)中查看所有可用选项及其生成的 JavaScript 代码。 ## TypeScript 命名空间 diff --git a/docs/documentation/zh/handbook-v2/More on Functions.md b/docs/documentation/zh/handbook-v2/More on Functions.md index 9a8436b..4351f4e 100644 --- a/docs/documentation/zh/handbook-v2/More on Functions.md +++ b/docs/documentation/zh/handbook-v2/More on Functions.md @@ -2,14 +2,14 @@ title: 函数进阶 layout: docs permalink: /zh/docs/handbook/2/functions.html -oneline: "学习 TypeScript 中函数的工作原理。" +oneline: "学习 TypeScript 中函数的工作原理" --- 函数是任何应用程序的基本构建块,它们可以是本地函数、从另一个模块导入的函数或者类的方法。它们也是值,并且与其他值一样,TypeScript 有很多方法来描述函数的调用方式。让我们来学习如何编写用于描述函数的类型。 ## 函数类型表达式 -描述函数的最简单方式是使用_函数类型表达式_。这些类型在语法上类似于箭头函数: +描述函数的最简单方式是使用*函数类型表达式*。这些类型在语法上类似于箭头函数: ```ts twoslash function greeter(fn: (a: string) => void) { @@ -38,7 +38,7 @@ function greeter(fn: GreetFunction) { ## 调用签名 -在 JavaScript 中,函数除了可以被调用之外,还可以有其他属性。然而,函数类型表达式语法不允许声明属性。如果我们想描述带有属性的可调用对象,可以在其对象类型中编写一个_调用签名(call signature)_: +在 JavaScript 中,函数除了可以被调用之外,还可以有其他属性。然而,函数类型表达式语法不允许声明属性。如果我们想描述带有属性的可调用对象,可以在其对象类型中编写一个*调用签名(call signature)*: ```ts twoslash type DescribableFunction = { @@ -95,7 +95,7 @@ function firstElement(arr: any[]) { 这个函数完成了它的工作,但不太好的是它的返回类型是 `any`。如果函数返回数组元素的类型会更好。 -在 TypeScript 中,当我们想要描述两个值之间的对应关系时,我们使用_泛型_。我们可以在函数签名中声明_类型参数_: +在 TypeScript 中,当我们想要描述两个值之间的对应关系时,我们使用*泛型*。我们可以在函数签名中声明*类型参数*: ```ts twoslash function firstElement(arr: Type[]): Type | undefined { @@ -118,7 +118,7 @@ const u = firstElement([]); ### 类型推断 -请注意,在这个示例中我们不必指定 `Type`。TypeScript 会自动_推断_类型。 +请注意,在这个示例中我们不必指定 `Type`。TypeScript 会自动*推断*类型。 我们也可以使用多个类型参数。例如,`map` 函数的独立版本如下: @@ -137,9 +137,9 @@ const parsed = map(["1", "2", "3"], (n) => parseInt(n)); ### 约束 -我们编写了一些泛型函数,可以适用于_任何_类型的值。有时候我们想要关联两个值,但只能对某个子集的类型的值进行操作。在这种情况下,我们可以使用_约束_来限制类型参数可以接受的类型的子集。 +我们编写了一些泛型函数,可以适用于*任何*类型的值。有时候我们想要关联两个值,但只能对某个子集的类型的值进行操作。在这种情况下,我们可以使用*约束*来限制类型参数可以接受的类型的子集。 -让我们编写一个返回两个值中较长的值的函数。为了做到这一点,我们需要值属于具有 `length` 属性的类型。我们通过编写 `extends` 子句将类型参数_约束_为该类型: +让我们编写一个返回两个值中较长的值的函数。为了做到这一点,我们需要值属于具有 `length` 属性的类型。我们通过编写 `extends` 子句将类型参数*约束*为该类型: ```ts twoslash // @errors: 2345 2322 @@ -159,7 +159,7 @@ const longerString = longest("alice", "bob"); const notOK = longest(10, 100); ``` -这个例子中有几个有趣的地方。我们允许 TypeScript _推断_ `longest` 的返回类型。返回类型推断也适用于泛型函数。 +这个例子中有几个有趣的地方。我们允许 TypeScript *推断* `longest` 的返回类型。返回类型推断也适用于泛型函数。 由于我们将 `Type` 约束为 `{ length: number }`,我们可以访问 `a` 和 `b` 参数的 `.length` 属性。如果没有类型约束,我们将无法访问这些属性,因为这些值可能是没有 length 属性的其他类型。 @@ -185,7 +185,7 @@ function minimumLength( } ``` -这个函数看起来可能没问题——`Type` 被约束为 `{ length: number }`,而函数要么返回 `Type` 类型的值,要么返回与该约束相匹配的值。问题在于该函数承诺返回与传入的对象_相同_类型的对象,而不仅仅是与约束匹配的_任意_对象。如果这段代码可以通过检查,那么你可以编写肯定不起作用的代码: +这个函数看起来可能没问题——`Type` 被约束为 `{ length: number }`,而函数要么返回 `Type` 类型的值,要么返回与该约束相匹配的值。问题在于该函数承诺返回与传入的对象*相同*类型的对象,而不仅仅是与约束匹配的*任意*对象。如果这段代码可以通过检查,那么你可以编写肯定不起作用的代码: ```ts twoslash declare function minimumLength( @@ -270,7 +270,7 @@ function filter2 boolean>( } ``` -我们创建了一个类型参数 `Func`,它_没有将任何两个值进行关联_。这总是一个警告信号,因为这意味着调用者想要指定类型参数时,必须手动为无关的类型参数指定额外的类型参数。`Func` 没有任何用处,只是让函数变得更难阅读和理解! +我们创建了一个类型参数 `Func`,它*没有将任何两个值进行关联*。这总是一个警告信号,因为这意味着调用者想要指定类型参数时,必须手动为无关的类型参数指定额外的类型参数。`Func` 没有任何用处,只是让函数变得更难阅读和理解! > **规则**:使用尽可能少的类型参数。 @@ -294,7 +294,7 @@ function greet(s: string) { } ``` -记住,类型参数是用于_关联多个值的类型_。如果类型参数在函数签名中只被使用一次,它就没有在关联任何内容。这包括推断的返回类型;例如,如果 `Str` 是 `greet` 的推断返回类型的一部分,它将关联参数和返回类型,因此在写入的代码中只出现一次,但实际上使用了两次。 +记住,类型参数是用于*关联多个值的类型*。如果类型参数在函数签名中只被使用一次,它就没有在关联任何内容。这包括推断的返回类型;例如,如果 `Str` 是 `greet` 的推断返回类型的一部分,它将关联参数和返回类型,因此在写入的代码中只出现一次,但实际上使用了两次。 > **规则**:如果一个类型参数只出现在一个位置,请仔细考虑是否真的需要它。 @@ -309,7 +309,7 @@ function f(n: number) { } ``` -我们可以在 TypeScript 中使用 `?` 将参数标记为_可选_: +我们可以在 TypeScript 中使用 `?` 将参数标记为*可选*: ```ts twoslash function f(x?: number) { @@ -321,7 +321,7 @@ f(10); // 可以 尽管参数的类型被指定为 `number`,但是因为 JavaScript 中未指定的参数其值被当作 `undefined`,所以 `x` 参数实际上具有类型 `number | undefined`。 -你还可以提供参数的_默认值_: +你还可以提供参数的*默认值*: ```ts twoslash function f(x = 10) { @@ -365,7 +365,7 @@ myForEach([1, 2, 3], (a) => console.log(a)); myForEach([1, 2, 3], (a, i) => console.log(a, i)); ``` -然而,_实际上_这样的话 _`callback` 只可能会被传递一个参数_。换句话说,函数定义表示其实现可能如下所示: +然而,*实际上*这样的话 *`callback` 只可能会被传递一个参数*。换句话说,函数定义表示其实现可能如下所示: ```ts twoslash // @errors: 2532 18048 @@ -394,13 +394,13 @@ myForEach([1, 2, 3], (a, i) => { 在 JavaScript 中,如果你用比参数多的实参调用一个函数,多余的实参会被忽略。TypeScript 的行为也是一样的。参数较少(类型相同)的函数总是可以替代参数较多的函数。 -> **规则**:在编写回调函数的函数类型时,除非你打算在_调用_函数时不传递该参数,否则_永远不要_编写可选参数。 +> **规则**:在编写回调函数的函数类型时,除非你打算在*调用*函数时不传递该参数,否则*永远不要*编写可选参数。 ## 函数重载 某些 JavaScript 函数可以以不同数量或类型的实参进行调用。例如,你可以编写函数来创建 `Date` 对象,它既可以接受时间戳作为参数(一个实参),也可以接受月份/日期/年份作为参数(三个实参)。 -在 TypeScript 中,我们可以通过编写_重载签名_来指定可以以不同方式调用的函数。为此,我们先编写一些函数签名(通常是两个或更多),然后再编写函数的具体实现: +在 TypeScript 中,我们可以通过编写*重载签名*来指定可以以不同方式调用的函数。为此,我们先编写一些函数签名(通常是两个或更多),然后再编写函数的具体实现: ```ts twoslash // @errors: 2575 @@ -418,9 +418,9 @@ const d2 = makeDate(5, 5, 5); const d3 = makeDate(1, 3); ``` -在这个示例中,我们编写了两个重载:一个接受一个参数,另一个接受三个参数。这两个签名被称为_重载签名_。 +在这个示例中,我们编写了两个重载:一个接受一个参数,另一个接受三个参数。这两个签名被称为*重载签名*。 -然后,我们编写了一个具体的函数实现,其签名与重载签名是兼容的。函数有一个_具体实现_签名,但这个签名不能直接调用。尽管我们在函数必需的参数后面写了两个可选参数,但它不能用两个参数调用! +然后,我们编写了一个具体的函数实现,其签名与重载签名是兼容的。函数有一个*具体实现*签名,但这个签名不能直接调用。尽管我们在函数必需的参数后面写了两个可选参数,但它不能用两个参数调用! ### 重载签名和具体实现签名 @@ -438,10 +438,10 @@ fn(); 同样,函数体的签名在外部是“看”不到的。 -> 外部无法看到_具体实现_的签名。 -> 当编写重载函数时,你应该始终在函数实现之前编写_两个_或更多的签名。 +> 外部无法看到*具体实现*的签名。 +> 当编写重载函数时,你应该始终在函数实现之前编写*两个*或更多的签名。 -具体实现的签名也必须与重载签名_兼容_。例如,下面的函数存在错误,因为具体实现的签名与重载签名不匹配: +具体实现的签名也必须与重载签名*兼容*。例如,下面的函数存在错误,因为具体实现的签名与重载签名不匹配: ```ts twoslash // @errors: 2394 @@ -475,7 +475,7 @@ function len(x: any) { } ``` -这个函数是无错误的;我们可以用字符串或数组调用它。然而,我们不能用可能是字符串_或_数组的值调用它,因为 TypeScript 只能解析函数调用为单个重载: +这个函数是无错误的;我们可以用字符串或数组调用它。然而,我们不能用可能是字符串*或*数组的值调用它,因为 TypeScript 只能解析函数调用为单个重载: ```ts twoslash // @errors: 2769 @@ -572,7 +572,7 @@ function noop() { ### `object` -特殊类型 `object` 指代任何非原始类型(`string`、`number`、`bigint`、`boolean`、`symbol`、`null` 或 `undefined`)的值。这与 _空对象类型_ `{ }` 不同,也不同于全局类型 `Object`。你可能永远不会使用 `Object`。 +特殊类型 `object` 指代任何非原始类型(`string`、`number`、`bigint`、`boolean`、`symbol`、`null` 或 `undefined`)的值。这与 *空对象类型* `{ }` 不同,也不同于全局类型 `Object`。你可能永远不会使用 `Object`。 > `object` 不是 `Object`。请**总是**使用 `object`! @@ -580,7 +580,7 @@ function noop() { ### `unknown` -`unknown` 类型表示_任意_值。这与 `any` 类型类似,但更安全,因为无法对 `unknown` 值进行任何操作: +`unknown` 类型表示*任意*值。这与 `any` 类型类似,但更安全,因为无法对 `unknown` 值进行任何操作: ```ts twoslash // @errors: 2571 18046 @@ -643,7 +643,7 @@ function doSomething(f: Function) { } ``` -这是一个_无类型的函数调用_,一般最好避免使用,因为它具有不安全的 `any` 返回类型。 +这是一个*无类型的函数调用*,一般最好避免使用,因为它具有不安全的 `any` 返回类型。 如果你需要接受任意函数但不打算调用它,类型 `() => void` 通常更安全。 @@ -658,7 +658,7 @@ function doSomething(f: Function) { ### 剩余参数 -除了使用可选参数或重载来创建可以接受各种固定参数数量的函数之外,我们还可以使用_剩余参数_定义可以接受**不确定数量**实参的函数。 +除了使用可选参数或重载来创建可以接受各种固定参数数量的函数之外,我们还可以使用*剩余参数*定义可以接受**不确定数量**实参的函数。 剩余参数位于其他参数之后,使用 `...` 语法: @@ -674,7 +674,7 @@ const a = multiply(10, 1, 2, 3, 4); ### 剩余实参 -相反地,我们可以使用扩展语法从可迭代对象(例如数组)中_提供_可变数量的实参。例如,数组的 `push` 方法接受任意数量的实参: +相反地,我们可以使用扩展语法从可迭代对象(例如数组)中*提供*可变数量的实参。例如,数组的 `push` 方法接受任意数量的实参: ```ts twoslash const arr1 = [1, 2, 3]; @@ -745,7 +745,7 @@ function sum({ a, b, c }: ABC) { 对于返回类型为 `void` 的函数,它们可能会产生一些不寻常但是符合预期的行为。 -使用返回类型为 `void` 的上下文类型并**不会**强制函数**不**返回任何值。换句话说,当实现一个带有 `void` 返回类型的上下文函数类型(`type voidFunc = () => void`)时,它可以返回_任何_其他值,但是该返回值会被忽略。 +使用返回类型为 `void` 的上下文类型并**不会**强制函数**不**返回任何值。换句话说,当实现一个带有 `void` 返回类型的上下文函数类型(`type voidFunc = () => void`)时,它可以返回*任何*其他值,但是该返回值会被忽略。 因此,以下 `() => void` 类型的实现是有效的: diff --git a/docs/documentation/zh/handbook-v2/Narrowing.md b/docs/documentation/zh/handbook-v2/Narrowing.md index d6ae329..a626662 100644 --- a/docs/documentation/zh/handbook-v2/Narrowing.md +++ b/docs/documentation/zh/handbook-v2/Narrowing.md @@ -2,7 +2,7 @@ title: 缩小类型范围 layout: docs permalink: /zh/docs/handbook/2/narrowing.html -oneline: "了解 TypeScript 如何利用 JavaScript 的知识来减少项目中的类型语法量。" +oneline: "了解 TypeScript 如何利用 JavaScript 的知识来减少项目中的类型语法量" --- 假设我们有一个名为 `padLeft` 的函数。 @@ -37,7 +37,7 @@ function padLeft(padding: number | string, input: string) { 虽然它看起来可能不起眼,但在这里实际上发生了很多事情。就像 TypeScript 使用静态类型分析运行时值一样,它还在 JavaScript 的运行时控制流构造(如 `if/else`、条件三元运算符、循环、真值检查等)上叠加了类型分析,这些构造都可以影响这些类型。 -在我们的 `if` 检查中,TypeScript 看到 `typeof padding === "number"` 并将其理解为特殊形式的代码,称为_类型守卫_。TypeScript 沿着程序可能采取的路径来分析值在给定位置的最具体可能类型。它查看这些特殊的检查(称为_类型守卫_)和赋值,并将类型细化为比声明更具体的类型的过程称为_缩小_。在许多编辑器中,我们可以观察到这些类型在变化,我们在示例中也将这样做。 +在我们的 `if` 检查中,TypeScript 看到 `typeof padding === "number"` 并将其理解为特殊形式的代码,称为*类型守卫*。TypeScript 沿着程序可能采取的路径来分析值在给定位置的最具体可能类型。它查看这些特殊的检查(称为*类型守卫*)和赋值,并将类型细化为比声明更具体的类型的过程称为*缩小*。在许多编辑器中,我们可以观察到这些类型在变化,我们在示例中也将这样做。 ```ts twoslash function padLeft(padding: number | string, input: string) { @@ -164,7 +164,7 @@ function printAll(strs: string | string[] | null) { 我们将整个函数体都包装在一个真值检查中,但这有一个微妙的缺点:我们可能不再能正确处理空字符串的情况。 -TypeScript 对我们来说没有任何问题,但如果你对 JavaScript 不太熟悉,这种行为值得注意。TypeScript 经常可以帮助你尽早发现错误,但如果你选择对一个值_什么也不做_,那么它能做的就有限了,而不会过于武断。如果你愿意,你可以通过使用一个代码检查工具来确保处理这类情况。 +TypeScript 对我们来说没有任何问题,但如果你对 JavaScript 不太熟悉,这种行为值得注意。TypeScript 经常可以帮助你尽早发现错误,但如果你选择对一个值*什么也不做*,那么它能做的就有限了,而不会过于武断。如果你愿意,你可以通过使用一个代码检查工具来确保处理这类情况。 关于通过真值缩小类型的最后一点是,带有 `!` 的布尔否定会将被否定的值过滤到否定分支。 @@ -173,10 +173,11 @@ function multiplyAll( values: number[] | undefined, factor: number ): number[] | undefined { - if (!values){ - return values; -} else { - return values.map((x) => x * factor); + if (!values) { + return values; + } else { + return values.map((x) => x * factor); + } } ``` @@ -280,7 +281,7 @@ function move(animal: Fish | Bird | Human) { ## `instanceof` 缩小类型 -JavaScript 中有一个运算符可以检查一个值是否是另一个值的“实例”。具体来说,在 JavaScript 中,`x instanceof Foo` 检查 `x` 的_原型链_是否包含 `Foo.prototype`。虽然我们不会在这里深入讨论,而且在我们介绍类时会更多地涉及到它,但它仍然对大多数可以使用 `new` 构造的值非常有用。正如你可能已经猜到的那样,`instanceof` 也是一种类型护卫,在由 `instanceof` 保护的分支中,TypeScript 会缩小类型范围。 +JavaScript 中有一个运算符可以检查一个值是否是另一个值的“实例”。具体来说,在 JavaScript 中,`x instanceof Foo` 检查 `x` 的*原型链*是否包含 `Foo.prototype`。虽然我们不会在这里深入讨论,而且在我们介绍类时会更多地涉及到它,但它仍然对大多数可以使用 `new` 构造的值非常有用。正如你可能已经猜到的那样,`instanceof` 也是一种类型护卫,在由 `instanceof` 保护的分支中,TypeScript 会缩小类型范围。 ```ts twoslash function logValue(x: Date | string) { @@ -311,7 +312,7 @@ console.log(x); // ^? ``` -请注意,每个赋值都有效。尽管在第一次赋值后,`x` 的观察类型变为 `number`,但我们仍然可以将 `string` 值赋值给 `x`。这是因为 `x` 的_声明类型_(`x` 起始的类型)是 `string | number`,而可赋值性始终根据声明类型进行检查。 +请注意,每个赋值都有效。尽管在第一次赋值后,`x` 的观察类型变为 `number`,但我们仍然可以将 `string` 值赋值给 `x`。这是因为 `x` 的*声明类型*(`x` 起始的类型)是 `string | number`,而可赋值性始终根据声明类型进行检查。 如果我们将 `boolean` 值赋值给 `x`,就会看到错误,因为它不是声明类型的一部分。 @@ -342,9 +343,9 @@ function padLeft(padding: number | string, input: string) { } ``` -`padLeft` 在其第一个 `if` 块中返回。TypeScript 能够分析这段代码,并看到在 `padding` 是 `number` 的情况下,函数体的其余部分(`return padding + input;`)是_不可达_的。因此,在函数的剩余部分中,它能够将 `number` 从 `padding` 的类型中移除(将 `string | number` 缩小为 `string`)。 +`padLeft` 在其第一个 `if` 块中返回。TypeScript 能够分析这段代码,并看到在 `padding` 是 `number` 的情况下,函数体的其余部分(`return padding + input;`)是*不可达*的。因此,在函数的剩余部分中,它能够将 `number` 从 `padding` 的类型中移除(将 `string | number` 缩小为 `string`)。 -这种基于可达性的代码分析称为_控制流分析_,TypeScript 在遇到类型守卫和赋值时使用这种流分析来缩小类型。分析变量时,控制流可以一次又一次地分裂和重新合并,并且该变量在每个点上都可能具有不同的类型。 +这种基于可达性的代码分析称为*控制流分析*,TypeScript 在遇到类型守卫和赋值时使用这种流分析来缩小类型。分析变量时,控制流可以一次又一次地分裂和重新合并,并且该变量在每个点上都可能具有不同的类型。 ```ts twoslash function example() { @@ -374,7 +375,7 @@ function example() { 到目前为止,我们已经使用现有的 JavaScript 构造来处理类型缩小,但有时你可能希望更直接地控制代码中的类型变化。 -要定义用户自定义的类型守卫,我们只需定义一个返回类型为_类型断言_的函数: +要定义用户自定义的类型守卫,我们只需定义一个返回类型为*类型断言*的函数: ```ts twoslash type Fish = { swim: () => void }; @@ -388,7 +389,7 @@ function isFish(pet: Fish | Bird): pet is Fish { 在这个示例中,`pet is Fish` 是我们的类型断言。断言采用 `parameterName is Type` 的形式,其中 `parameterName` 必须是当前函数签名中的参数名称。 -每当使用某个变量调用 `isFish` 时,TypeScript 将会根据原始类型是否兼容,将该变量_缩小_为特定类型。 +每当使用某个变量调用 `isFish` 时,TypeScript 将会根据原始类型是否兼容,将该变量*缩小*为特定类型。 ```ts twoslash type Fish = { swim: () => void }; @@ -408,7 +409,7 @@ if (isFish(pet)) { } ``` -请注意,TypeScript 不仅知道在 `if` 分支中 `pet` 是 `Fish`;它还知道在 `else` 分支中,其_并非_`Fish`,所以它肯定是 `Bird`。 +请注意,TypeScript 不仅知道在 `if` 分支中 `pet` 是 `Fish`;它还知道在 `else` 分支中,其*并非*`Fish`,所以它肯定是 `Bird`。 你可以使用类型守卫 `isFish` 来过滤 `Fish | Bird` 数组,并获得 `Fish` 数组: @@ -524,7 +525,7 @@ function getArea(shape: Shape) { 但这并不是理想的解决方法。我们不得不在类型检查器面前大声喊出这些非空断言(`!`),以说服它 `shape.radius` 是定义过的,但是如果我们开始调整代码,这些断言就容易出错。此外,在[`strictNullChecks`](/tsconfig#strictNullChecks) 之外,我们仍然可以意外访问这些字段(因为在读取它们时,可选属性被假定为始终存在)。我们肯定可以做得更好。 -这种 `Shape` 的编码方式的问题在于,类型检查器无法根据 `kind` 属性知道 `radius` 或 `sideLength` 是否存在。我们需要将_我们_所了解的信息传达给类型检查器。考虑到这一点,让我们尝试另一种方法来定义 `Shape`。 +这种 `Shape` 的编码方式的问题在于,类型检查器无法根据 `kind` 属性知道 `radius` 或 `sideLength` 是否存在。我们需要将*我们*所了解的信息传达给类型检查器。考虑到这一点,让我们尝试另一种方法来定义 `Shape`。 ```ts twoslash interface Circle { @@ -590,9 +591,9 @@ function getArea(shape: Shape) { } ``` -这样就消除了错误!当联合类型的每个成员都包含具有字面类型的共同属性时,TypeScript 将其视为_可辨识联合_,并可以排除联合的成员。 +这样就消除了错误!当联合类型的每个成员都包含具有字面类型的共同属性时,TypeScript 将其视为*可辨识联合*,并可以排除联合的成员。 -在这种情况下,`kind` 就是这个共同属性(被认为是 `Shape` 的_辨识属性_)。检查 `kind` 属性是否为 `"circle"` 可以排除 `Shape` 中没有具有类型为 `"circle"` 的 `kind` 属性的类型。这将 `shape` 缩小为类型 `Circle`。 +在这种情况下,`kind` 就是这个共同属性(被认为是 `Shape` 的*辨识属性*)。检查 `kind` 属性是否为 `"circle"` 可以排除 `Shape` 中没有具有类型为 `"circle"` 的 `kind` 属性的类型。这将 `shape` 缩小为类型 `Circle`。 相同的检查也适用于 `switch` 语句。现在我们可以尝试编写完整的 `getArea` 函数,而无需使用烦人的 `!` 非空断言。 diff --git a/docs/documentation/zh/handbook-v2/Object Types.md b/docs/documentation/zh/handbook-v2/Object Types.md index 75a8b45..be5b8b9 100644 --- a/docs/documentation/zh/handbook-v2/Object Types.md +++ b/docs/documentation/zh/handbook-v2/Object Types.md @@ -2,10 +2,10 @@ title: 对象类型 layout: docs permalink: /zh/docs/handbook/2/objects.html -oneline: "TypeScript 描述 JavaScript 对象的方式。" +oneline: "TypeScript 描述 JavaScript 对象的方式" --- -在 JavaScript 中,对象是我们最基本的组织和传递数据的方式。在 TypeScript 中,我们通过_对象类型_来表示它们。 +在 JavaScript 中,对象是我们最基本的组织和传递数据的方式。在 TypeScript 中,我们通过*对象类型*来表示它们。 正如我们所见,它们可以是匿名的: @@ -56,7 +56,7 @@ function greet(person: Person) { ### 可选属性 -大部分情况下,我们处理的对象_可能_会有某些属性设置。在这种情况下,我们可以通过在属性名称末尾添加问号(`?`)来将这些属性标记为_可选_。 +大部分情况下,我们处理的对象*可能*会有某些属性设置。在这种情况下,我们可以通过在属性名称末尾添加问号(`?`)来将这些属性标记为*可选*。 ```ts twoslash interface Shape {} @@ -150,7 +150,7 @@ function paintShape({ shape, xPos = 0, yPos = 0 }: PaintOptions) { } ``` -在这里,我们使用了[解构赋值模式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 来定义 `paintShape` 的参数,并为 `xPos` 和 `yPos` 提供了[默认值](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#默认值)。现在,在 `paintShape` 函数体内,`xPos` 和 `yPos` 都是必然存在的,但对于 `paintShape` 的调用者来说是可选的。 +在这里,我们使用了[解构赋值模式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring*assignment) 来定义 `paintShape` 的参数,并为 `xPos` 和 `yPos` 提供了[默认值](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring*assignment#默认值)。现在,在 `paintShape` 函数体内,`xPos` 和 `yPos` 都是必然存在的,但对于 `paintShape` 的调用者来说是可选的。 > 注意,目前无法在解构赋值模式中放置类型注解。 > 这是因为在 JavaScript 中,以下语法已经具有不同的含义。 @@ -346,11 +346,11 @@ function createSquare(config: SquareConfig): { color: string; area: number } { let mySquare = createSquare({ colour: "red", width: 100 }); ``` -注意,传递给 `createSquare` 的参数中将 `color` 拼写为 _`colour`_ 而不是 `color`。在普通的 JavaScript 中,这种情况会悄无声息地失败。 +注意,传递给 `createSquare` 的参数中将 `color` 拼写为 *`colour`* 而不是 `color`。在普通的 JavaScript 中,这种情况会悄无声息地失败。 你可以认为这个程序是正确类型化的,因为 `width` 属性是兼容的,没有 `color` 属性存在,并且额外的 `colour` 属性是无关紧要的。 -然而,TypeScript 认为这段代码可能存在 bug。对象字面量在赋值给其他变量或作为实参传递时会经历_额外的属性检查_。如果对象字面量具有任何目标类型不具备的属性,就会产生错误: +然而,TypeScript 认为这段代码可能存在 bug。对象字面量在赋值给其他变量或作为实参传递时会经历*额外的属性检查*。如果对象字面量具有任何目标类型不具备的属性,就会产生错误: ```ts twoslash // @errors: 2345 2739 @@ -388,7 +388,7 @@ function createSquare(config: SquareConfig): { color: string; area: number } { let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig); ``` -然而,如果你确定该对象可以具有一些额外的属性,并且这些属性在某种特殊方式下使用,一种更好的方法是在对象上添加字符串索引签名。如果 `SquareConfig` 可以具有上述类型的 `color` 和 `width` 属性,但_还_可以具有任意数量的其他属性,那么我们可以这样定义它: +然而,如果你确定该对象可以具有一些额外的属性,并且这些属性在某种特殊方式下使用,一种更好的方法是在对象上添加字符串索引签名。如果 `SquareConfig` 可以具有上述类型的 `color` 和 `width` 属性,但*还*可以具有任意数量的其他属性,那么我们可以这样定义它: ```ts twoslash interface SquareConfig { @@ -512,7 +512,7 @@ const cc: ColorfulCircle = { ## 交叉类型 -在 TypeScript 中,除了使用 `interface` 来扩展已有类型外,还提供了另一种构造方式,称为_交叉类型(intersection types)_,主要用于组合现有的对象类型。 +在 TypeScript 中,除了使用 `interface` 来扩展已有类型外,还提供了另一种构造方式,称为*交叉类型(intersection types)*,主要用于组合现有的对象类型。 交叉类型使用 `&` 运算符进行定义。 @@ -527,7 +527,7 @@ interface Circle { type ColorfulCircle = Colorful & Circle; ``` -在这个例子中,我们对 `Colorful` 和 `Circle` 进行了交叉,生成了新类型,该类型具有 `Colorful` _和_ `Circle` 的所有成员。 +在这个例子中,我们对 `Colorful` 和 `Circle` 进行了交叉,生成了新类型,该类型具有 `Colorful` *和* `Circle` 的所有成员。 ```ts twoslash // @errors: 2345 @@ -633,7 +633,7 @@ function setContents(box: { contents: any }, newContents: any) { 有很多样板代码。而且,以后我们可能需要引入新的类型和重载。这很令人沮丧,因为我们的盒子类型和重载实际上是相同的。 -相反,我们可以创建声明_类型参数_的_泛型_ `Box` 类型。 +相反,我们可以创建声明*类型参数*的*泛型* `Box` 类型。 ```ts twoslash interface Box { @@ -641,7 +641,7 @@ interface Box { } ``` -你可以将其理解为“`Type` 类型的 `Box` 是具有类型为 `Type` 的 `contents` 的东西”。在稍后引用 `Box` 时,我们必须在 `Type` 的位置上给出一个_类型参数_。 +你可以将其理解为“`Type` 类型的 `Box` 是具有类型为 `Type` 的 `contents` 的东西”。在稍后引用 `Box` 时,我们必须在 `Type` 的位置上给出一个*类型参数*。 ```ts twoslash interface Box { @@ -839,7 +839,7 @@ y = x; ### 元组类型 -_元组类型_是另一种 `Array` 类型,它确切地知道它包含多少个元素,以及在特定位置包含的确切类型。 +*元组类型*是另一种 `Array` 类型,它确切地知道它包含多少个元素,以及在特定位置包含的确切类型。 ```ts twoslash type StringNumberPair = [string, number]; diff --git a/docs/documentation/zh/handbook-v2/The Handbook.md b/docs/documentation/zh/handbook-v2/The Handbook.md index 2d69b4e..d611abc 100644 --- a/docs/documentation/zh/handbook-v2/The Handbook.md +++ b/docs/documentation/zh/handbook-v2/The Handbook.md @@ -12,7 +12,7 @@ handbook: "true" 程序员常犯的最常见错误是类型错误:在期望使用某种类型的值时使用了另外一种类型的值。这可能是由于简单的拼写错误、未理解库的 API、对运行时行为的错误假设或其他错误导致的。TypeScript 的目标是成为 JavaScript 程序的静态类型检查器,也就是说,在你的代码运行之前(静态)运行的工具,确保程序的类型是正确的(类型检查)。 -如果你没有 JavaScript 背景,打算把 TypeScript 作为你的第一门语言学习,我们建议你首先阅读 [微软 JavaScript 学习教程](https://developer.microsoft.com/javascript/)或阅读 [Mozilla Web 文档中的 JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Guide)教程。 +如果你没有 JavaScript 背景,打算把 TypeScript 作为你的第一门语言学习,我们建议你首先阅读 [微软 JavaScript 学习教程](https://developer.microsoft.com/javascript/)或阅读 [Mozilla Web 文档中的 JavaScript](https://developer.mozilla.org/docs/Web/JavaScript/Guide) 教程。 如果你有其他语言的经验,通过阅读本手册,你应该能够很快掌握 JavaScript 语法。 @@ -50,11 +50,11 @@ handbook: "true" ## 开始学习 -在开始学习[基础知识](/docs/handbook/2/basic-types.html) 之前,我们建议挑一个以下介绍页面阅读。这些介绍旨在突出 TypeScript 与你喜欢的编程语言之间的主要相似性和差异,并澄清与这些语言特定的常见误解。 +在开始学习[基础知识](/docs/handbook/2/basic-types.html)之前,我们建议挑一个以下介绍页面阅读。这些介绍旨在突出 TypeScript 与你喜欢的编程语言之间的主要相似性和差异,并澄清与这些语言特定的常见误解。 - [适用于新程序员的 TypeScript](/docs/handbook/typescript-from-scratch.html) - [适用于 JavaScript 程序员的 TypeScript](/docs/handbook/typescript-in-5-minutes.html) -- [适用于 Java/C#程序员的 TypeScript](/docs/handbook/typescript-in-5-minutes-oop.html) +- [适用于 Java/C# 程序员的 TypeScript](/docs/handbook/typescript-in-5-minutes-oop.html) - [适用于函数式程序员的 TypeScript](/docs/handbook/typescript-in-5-minutes-func.html) 否则,你可以直接跳转到[基础知识](/docs/handbook/2/basic-types.html) 部分。 diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md index 2cbc400..aebd696 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md @@ -2,10 +2,10 @@ title: 条件类型 layout: docs permalink: /zh/docs/handbook/2/conditional-types.html -oneline: "创建类似于类型系统中 if 语句的类型。" +oneline: "创建类似于类型系统中 if 语句的类型" --- -大多数有效程序的核心是,我们必须依据输入做出一些决定。JavaScript 程序也是如此,但是由于值可以很容易地被内省,这些决定也是基于输入的类型。_条件类型_有助于描述输入和输出类型之间的关系。 +大多数有效程序的核心是,我们必须依据输入做出一些决定。JavaScript 程序也是如此,但是由于值可以很容易地被内省,这些决定也是基于输入的类型。*条件类型*有助于描述输入和输出类型之间的关系。 ```ts twoslash interface Animal { @@ -151,7 +151,7 @@ type DogMessageContents = MessageOf; // ^? ``` -在 true 分支中,TypeScript 知道 `T` _会_有 `message` 属性。 +在 true 分支中,TypeScript 知道 `T` *会*有 `message` 属性。 举另一个示例,我们还可以编写名为 `Flatten` 的类型,如果是数组类型的话,将其类型展平为其元素类型,否则类型保持不变: @@ -198,7 +198,7 @@ type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // ^? ``` -当从具有多个调用签名的类型(如重载函数的类型)进行推断时,将从_最后一个_签名进行推断(这也许是最宽松的万能情况)。无法基于实参类型列表对重载函数进行决策。 +当从具有多个调用签名的类型(如重载函数的类型)进行推断时,将从*最后一个*签名进行推断(这也许是最宽松的万能情况)。无法基于实参类型列表对重载函数进行决策。 ```ts twoslash declare function stringOrNum(x: string): number; @@ -211,7 +211,7 @@ type T1 = ReturnType; ## 分布式条件类型 -当条件类型作用于泛型类型时,如果给定一个联合类型,它们就变成了_分布式_类型。例如,考虑以下代码: +当条件类型作用于泛型类型时,如果给定一个联合类型,它们就变成了*分布式*类型。例如,考虑以下代码: ```ts twoslash type ToArray = Type extends any ? Type[] : never; diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md index 562e09f..9022391 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md @@ -7,7 +7,7 @@ oneline: 带有参数的类型 软件工程中的一个要点,是构建具有明确定义且一致的 API 的组件,同时这些组件还要具备可重用性。既能够处理当下数据,也能够处理未来数据的组件,将帮助你更加灵活地构建大型软件系统。 -在像 C# 和 Java 这样的语言中,创建可重用组件的主要工具之一是_泛型_,即能够创建可以处理多种类型而不仅限于单一类型的组件。这允许用户使用自己的类型来使用这些组件。 +在像 C# 和 Java 这样的语言中,创建可重用组件的主要工具之一是*泛型*,即能够创建可以处理多种类型而不仅限于单一类型的组件。这允许用户使用自己的类型来使用这些组件。 ## 泛型的 Hello World @@ -31,7 +31,7 @@ function identity(arg: any): any { 虽然使用 `any` 使函数接收任何类型的 `arg` 具有泛型的特性,但是我们将丢失有关返回类型的信息。如果我们传入数字,我们只知道任何类型都可能返回。 -相反,我们需要一种能够捕获参数类型并在返回类型中使用它的方式。在这里,我们将使用_类型变量_,这是一种特殊类型的变量,用于处理类型而不是值。 +相反,我们需要一种能够捕获参数类型并在返回类型中使用它的方式。在这里,我们将使用*类型变量*,这是一种特殊类型的变量,用于处理类型而不是值。 ```ts twoslash function identity(arg: Type): Type { @@ -56,7 +56,7 @@ let output = identity("myString"); 这里我们明确将 `Type` 设置为函数调用的一个实参(即 `string`),使用 `<>` 将参数括起来而不是 `()`。 -第二种方式也许是最常用的。这里我们使用_类型参数推断_——即,我们让编译器根据我们传入的实参的类型自动为我们设置 `Type` 的值: +第二种方式也许是最常用的。这里我们使用*类型参数推断*——即,我们让编译器根据我们传入的实参的类型自动为我们设置 `Type` 的值: ```ts twoslash function identity(arg: Type): Type { @@ -223,7 +223,7 @@ console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); ## 通用约束 -如果你还记得之前的例子,有时你可能希望编写一个通用函数,该函数适用于一组类型,你对该类型集合的某些特点有_一些_了解。在我们的 `loggingIdentity` 示例中,我们希望能够访问 `arg` 的 `.length` 属性,但编译器无法证明每种类型都有 `.length` 属性,所以它警告我们不能做出这种假设。 +如果你还记得之前的例子,有时你可能希望编写一个通用函数,该函数适用于一组类型,你对该类型集合的某些特点有*一些*了解。在我们的 `loggingIdentity` 示例中,我们希望能够访问 `arg` 的 `.length` 属性,但编译器无法证明每种类型都有 `.length` 属性,所以它警告我们不能做出这种假设。 ```ts twoslash // @errors: 2339 diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md index 5f354e9..010a0c3 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md @@ -2,10 +2,10 @@ title: 索引访问类型 layout: docs permalink: /zh/docs/handbook/2/indexed-access-types.html -oneline: "使用 Type['a'] 语法访问类型的子集。" +oneline: "使用 Type['a'] 语法访问类型的子集" --- -我们可以使用_索引访问类型_在另一个类型上查找特定的属性: +我们可以使用*索引访问类型*在另一个类型上查找特定的属性: ```ts twoslash type Person = { age: number; name: string; alive: boolean }; diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md index 58f35c6..13afd3f 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md @@ -83,7 +83,7 @@ person.on("firstNameChanged", (newValue) => { }); ``` -注意,`on` 监听的事件是 `"firstNameChanged"`,而不仅仅是 `"firstName"`。如果我们能确保符合属性名集合与末尾添加“Changed”的并集的约束,我们可以使 `on()` 的规范更加强大。虽然我们在 JavaScript 中可以轻松进行这样的计算,即 ``Object.keys(passedObject).map(x => `${x}Changed`)``,但是_在类型系统中_,模板字面类型提供了类似的字符串处理方法: +注意,`on` 监听的事件是 `"firstNameChanged"`,而不仅仅是 `"firstName"`。如果我们能确保符合属性名集合与末尾添加“Changed”的并集的约束,我们可以使 `on()` 的规范更加强大。虽然我们在 JavaScript 中可以轻松进行这样的计算,即 ``Object.keys(passedObject).map(x => `${x}Changed`)``,但是*在类型系统中*,模板字面类型提供了类似的字符串处理方法: ```ts twoslash type PropEventSource = { diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md index f85c5e9..f4b7c92 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md @@ -7,14 +7,14 @@ oneline: "在类型上下文中使用 typeof 运算符。" ## `typeof` 类型运算符 -JavaScript 已经有了 `typeof` 运算符,你可以在_表达式_上下文中使用它: +JavaScript 已经有了 `typeof` 运算符,你可以在*表达式*上下文中使用它: ```ts twoslash // 输出 "string" console.log(typeof "Hello world"); ``` -TypeScript 添加了 `typeof` 运算符,你可以在_类型_上下文中使用它来引用变量或属性的 _类型_: +TypeScript 添加了 `typeof` 运算符,你可以在*类型*上下文中使用它来引用变量或属性的 *类型*: ```ts twoslash let s = "hello"; @@ -22,7 +22,7 @@ let n: typeof s; // ^? ``` -对于基本类型,这并不是很有用,但是如果与其他类型运算符结合使用,你就可以方便地表达许多模式。例如,让我们首先看一下预定义类型 `ReturnType`。它接受_函数类型_为参数并生成其返回类型: +对于基本类型,这并不是很有用,但是如果与其他类型运算符结合使用,你就可以方便地表达许多模式。例如,让我们首先看一下预定义类型 `ReturnType`。它接受*函数类型*为参数并生成其返回类型: ```ts twoslash type Predicate = (x: unknown) => boolean; @@ -40,7 +40,7 @@ function f() { type P = ReturnType; ``` -请记住,_值_和_类型_不是相同的东西。要引用_值 `f`_ 具有的_类型_,我们使用 `typeof`: +请记住,*值*和*类型*不是相同的东西。要引用*值 `f`* 具有的*类型*,我们使用 `typeof`: ```ts twoslash function f() { diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md index 8970a7d..c736fe7 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md @@ -2,12 +2,12 @@ title: 用现有类型创建新类型 layout: docs permalink: /zh/docs/handbook/2/types-from-types.html -oneline: "概述如何从现有的类型创建更多的类型。" +oneline: "概述如何从现有的类型创建更多的类型" --- -TypeScript 的类型系统非常强大,因为它允许用_其他类型_表达类型。 +TypeScript 的类型系统非常强大,因为它允许用*其他类型*表达类型。 -这个想法最简单的形式就是泛型。此外,我们还有多种_类型操作符_可以使用。我们也可以用我们已有的_值_表达类型。 +这个想法最简单的形式就是泛型。此外,我们还有多种*类型操作符*可以使用。我们也可以用我们已有的*值*表达类型。 通过组合不同的类型操作符,我们可以用简洁、可维护的方式表达复杂的操作和值。在本部分中,我们将介绍如何用现有的类型或值表达新的类型。