From 1f9ab310e243f4fd10069306784fb336f29cdf64 Mon Sep 17 00:00:00 2001
From: zhongsp
Date: Sun, 7 Apr 2024 11:55:09 +0800
Subject: [PATCH] satisfy lint
---
PREFACE.md | 2 +-
lint.js | 4 +-
zh/breaking-changes/README.md | 43 +-
zh/breaking-changes/typescript-1.4.md | 66 +-
zh/breaking-changes/typescript-1.5.md | 115 +--
zh/breaking-changes/typescript-1.6.md | 79 +-
zh/breaking-changes/typescript-1.7.md | 37 +-
zh/breaking-changes/typescript-1.8.md | 1 -
zh/breaking-changes/typescript-2.0.md | 57 +-
zh/breaking-changes/typescript-2.1.md | 99 ++-
zh/breaking-changes/typescript-2.2.md | 7 +-
zh/breaking-changes/typescript-2.3.md | 7 +-
zh/breaking-changes/typescript-2.4.md | 51 +-
zh/breaking-changes/typescript-2.6.md | 27 +-
zh/breaking-changes/typescript-2.7.md | 40 +-
zh/breaking-changes/typescript-2.8.md | 41 +-
zh/breaking-changes/typescript-2.9.md | 20 +-
zh/breaking-changes/typescript-3.0.md | 5 +-
zh/breaking-changes/typescript-3.1.md | 177 +++-
zh/breaking-changes/typescript-3.2.md | 3 +-
zh/breaking-changes/typescript-3.4.md | 48 +-
zh/breaking-changes/typescript-3.5.md | 1 -
zh/breaking-changes/typescript-3.6.md | 19 +-
zh/declaration-files/README.md | 18 +-
zh/declaration-files/by-example.md | 78 +-
zh/declaration-files/deep-dive.md | 50 +-
zh/declaration-files/do-s-and-don-ts.md | 30 +-
zh/declaration-files/introduction.md | 14 +-
zh/declaration-files/library-structures.md | 42 +-
zh/declaration-files/publishing.md | 78 +-
zh/declaration-files/templates.md | 15 +-
.../templates/global-plugin.d.ts.md | 32 +-
zh/declaration-files/templates/global.d.ts.md | 90 +--
zh/handbook-v2/basics.md | 50 +-
zh/handbook-v2/classes.md | 167 ++--
zh/handbook-v2/everyday-types.md | 104 +--
zh/handbook-v2/modules.md | 46 +-
zh/handbook-v2/more-on-functions.md | 49 +-
zh/handbook-v2/narrowing.md | 111 ++-
zh/handbook-v2/object-types.md | 3 +-
zh/handbook/basic-types.md | 109 +--
zh/handbook/classes.md | 361 +++++----
zh/handbook/enums.md | 181 +++--
zh/handbook/functions.md | 326 ++++----
zh/handbook/generics.md | 123 +--
zh/handbook/interfaces.md | 69 +-
zh/handbook/literal-types.md | 1 -
.../type-checking-javascript-files.md | 1 -
zh/project-config/README.md | 16 +-
.../compiler-options-in-msbuild.md | 1 -
zh/project-config/compiler-options.md | 1 -
zh/project-config/configuring-watch.md | 1 -
.../integrating-with-build-tools.md | 1 -
zh/project-config/project-references.md | 1 -
zh/project-config/tsconfig.json.md | 1 -
zh/reference/advanced-types.md | 754 +++++++++---------
zh/reference/declaration-merging.md | 189 +++--
zh/reference/decorators.md | 428 +++++-----
zh/reference/iterators-and-generators.md | 27 +-
zh/reference/jsx.md | 128 +--
zh/reference/mixins.md | 102 +--
zh/reference/module-resolution.md | 112 ++-
zh/reference/modules.md | 524 ++++++------
zh/reference/namespaces-and-modules.md | 61 +-
zh/reference/namespaces.md | 171 ++--
zh/reference/symbols.md | 29 +-
zh/reference/triple-slash-directives.md | 55 +-
zh/reference/type-compatibility.md | 114 +--
zh/reference/type-inference.md | 41 +-
zh/reference/utility-types.md | 116 +--
zh/reference/variable-declarations.md | 277 +++----
zh/release-notes/README.md | 85 +-
zh/release-notes/typescript-1.1.md | 7 +-
zh/release-notes/typescript-1.3.md | 9 +-
zh/release-notes/typescript-1.4.md | 102 +--
zh/release-notes/typescript-1.5.md | 99 +--
zh/release-notes/typescript-1.6.md | 210 ++---
zh/release-notes/typescript-1.7.md | 140 ++--
zh/release-notes/typescript-1.8.md | 257 +++---
zh/release-notes/typescript-2.0.md | 516 ++++++------
zh/release-notes/typescript-2.1.md | 268 ++++---
zh/release-notes/typescript-2.2.md | 113 +--
zh/release-notes/typescript-2.3.md | 67 +-
zh/release-notes/typescript-2.4.md | 69 +-
zh/release-notes/typescript-2.5.md | 22 +-
zh/release-notes/typescript-2.6.md | 87 +-
zh/release-notes/typescript-2.7.md | 221 ++---
zh/release-notes/typescript-2.8.md | 289 +++----
zh/release-notes/typescript-2.9.md | 175 ++--
zh/release-notes/typescript-3.0.md | 219 ++---
zh/release-notes/typescript-3.1.md | 35 +-
zh/release-notes/typescript-3.2.md | 130 ++-
zh/release-notes/typescript-3.3.md | 33 +-
zh/release-notes/typescript-3.4.md | 116 ++-
zh/release-notes/typescript-3.5.md | 52 +-
zh/release-notes/typescript-3.6.md | 69 +-
zh/release-notes/typescript-3.7.md | 476 ++++++-----
zh/release-notes/typescript-3.8.md | 285 ++++---
zh/release-notes/typescript-3.9.md | 110 +--
zh/release-notes/typescript-4.0.md | 222 +++---
zh/release-notes/typescript-4.1.md | 276 ++++---
zh/release-notes/typescript-4.2.md | 162 ++--
zh/release-notes/typescript-4.3.md | 247 +++---
zh/release-notes/typescript-4.4.md | 381 +++------
zh/release-notes/typescript-4.5.md | 70 +-
zh/release-notes/typescript-4.6.md | 161 ++--
zh/release-notes/typescript-4.7.md | 327 ++++----
zh/release-notes/typescript-4.8.md | 71 +-
zh/release-notes/typescript-4.9.md | 206 ++---
zh/release-notes/typescript-5.0.md | 12 +-
zh/release-notes/typescript-5.1.md | 2 +-
zh/release-notes/typescript-5.2.md | 30 +-
zh/release-notes/typescript-5.4.md | 4 +-
zh/tutorials/angular-2.md | 5 +-
zh/tutorials/asp.net-4.md | 39 +-
zh/tutorials/asp.net-core.md | 85 +-
zh/tutorials/gulp.md | 208 ++---
zh/tutorials/knockout.md | 51 +-
zh/tutorials/migrating-from-javascript.md | 247 +++---
zh/tutorials/react-and-webpack.md | 161 ++--
zh/tutorials/react.md | 220 ++---
zh/tutorials/typescript-in-5-minutes.md | 83 +-
zh/wiki/README.md | 15 +-
zh/wiki/architectural-overview.md | 72 +-
zh/wiki/coding_guidelines.md | 47 +-
zh/wiki/common-errors.md | 7 +-
zh/wiki/roadmap.md | 211 +++--
zh/wiki/this-in-typescript.md | 90 +--
zh/wiki/typescript-editor-support.md | 53 +-
zh/wiki/using-typescript-with-asp.net-5.md | 23 +-
130 files changed, 7330 insertions(+), 6966 deletions(-)
diff --git a/PREFACE.md b/PREFACE.md
index 0c31035a..3fa126a9 100644
--- a/PREFACE.md
+++ b/PREFACE.md
@@ -1,6 +1,6 @@
# 前言
-> Repo: https://github.com/zhongsp/TypeScript
+> Repo: [https://github.com/zhongsp/TypeScript](https://github.com/zhongsp/TypeScript)
该工程是对 TypeScript 官方及开源社区书写的编程手册、版本发布说明等综合内容的中文翻译。
感谢 Microsoft 和开源社区的工程师们的工作,为 JavaScript 开发带来了全新的体验!
diff --git a/lint.js b/lint.js
index 729ee081..82276a6f 100644
--- a/lint.js
+++ b/lint.js
@@ -9,7 +9,7 @@ var options = {
MD001: false, // Header levels should only increment by one level at a time
MD002: false, // First header should be a h1 header
MD003: "atx", // Header style
- MD004: { style: "asterisk" }, // Unordered list style
+ MD004: { style: "consistent" }, // Unordered list style
MD005: true, // Inconsistent indentation for list items at the same level
MD006: true, // Consider starting bulleted lists at the beginning of the line
MD007: { indent: 2 }, // Unordered list indentation
@@ -30,7 +30,7 @@ var options = {
MD026: { punctuation: ".,;:!" }, // Trailing punctuation in header
MD027: true, // Multiple spaces after blockquote symbol
MD028: true, // Blank line inside blockquote
- MD029: { style: "ordered" }, // Ordered list item prefix
+ MD029: { style: "one_or_ordered" }, // Ordered list item prefix
MD030: true, // Spaces after list markers
MD031: true, // Fenced code blocks should be surrounded by blank lines
MD032: true, // Lists should be surrounded by blank lines
diff --git a/zh/breaking-changes/README.md b/zh/breaking-changes/README.md
index 93ad2432..96cc1493 100644
--- a/zh/breaking-changes/README.md
+++ b/zh/breaking-changes/README.md
@@ -1,24 +1,23 @@
# Breaking Changes
-* [TypeScript 3.6](typescript-3.6.md)
-* [TypeScript 3.5](typescript-3.5.md)
-* [TypeScript 3.4](typescript-3.4.md)
-* [TypeScript 3.2](typescript-3.2.md)
-* [TypeScript 3.1](typescript-3.1.md)
-* [TypeScript 3.0](typescript-3.0.md)
-* [TypeScript 2.9](typescript-2.9.md)
-* [TypeScript 2.8](typescript-2.8.md)
-* [TypeScript 2.7](typescript-2.7.md)
-* [TypeScript 2.6](typescript-2.6.md)
-* [TypeScript 2.4](typescript-2.4.md)
-* [TypeScript 2.3](typescript-2.3.md)
-* [TypeScript 2.2](typescript-2.2.md)
-* [TypeScript 2.1](typescript-2.1.md)
-* [TypeScript 2.0](typescript-2.0.md)
-* [TypeScript 1.8](typescript-1.8.md)
-* [TypeScript 1.7](typescript-1.7.md)
-* [TypeScript 1.6](typescript-1.6.md)
-* [TypeScript 1.5](typescript-1.5.md)
-* [TypeScript 1.4](typescript-1.4.md)
-* [TypeScript 1.1](typescript-1.1.md)
-
+- [TypeScript 3.6](typescript-3.6.md)
+- [TypeScript 3.5](typescript-3.5.md)
+- [TypeScript 3.4](typescript-3.4.md)
+- [TypeScript 3.2](typescript-3.2.md)
+- [TypeScript 3.1](typescript-3.1.md)
+- [TypeScript 3.0](typescript-3.0.md)
+- [TypeScript 2.9](typescript-2.9.md)
+- [TypeScript 2.8](typescript-2.8.md)
+- [TypeScript 2.7](typescript-2.7.md)
+- [TypeScript 2.6](typescript-2.6.md)
+- [TypeScript 2.4](typescript-2.4.md)
+- [TypeScript 2.3](typescript-2.3.md)
+- [TypeScript 2.2](typescript-2.2.md)
+- [TypeScript 2.1](typescript-2.1.md)
+- [TypeScript 2.0](typescript-2.0.md)
+- [TypeScript 1.8](typescript-1.8.md)
+- [TypeScript 1.7](typescript-1.7.md)
+- [TypeScript 1.6](typescript-1.6.md)
+- [TypeScript 1.5](typescript-1.5.md)
+- [TypeScript 1.4](typescript-1.4.md)
+- [TypeScript 1.1](typescript-1.1.md)
diff --git a/zh/breaking-changes/typescript-1.4.md b/zh/breaking-changes/typescript-1.4.md
index f311864f..22cf7d78 100644
--- a/zh/breaking-changes/typescript-1.4.md
+++ b/zh/breaking-changes/typescript-1.4.md
@@ -27,20 +27,28 @@ var bs: { x: number; y?: number; z?: number }[] = [b, a];
## 泛型接口
-当在多个T类型的参数上使用了不同的类型时会得到一个错误,就算是添加约束也不行:
+当在多个 T 类型的参数上使用了不同的类型时会得到一个错误,就算是添加约束也不行:
```typescript
-declare function foo(x: T, y:T): T;
-var r = foo(1, ""); // r used to be {}, now this is an error
+declare function foo(x: T, y: T): T;
+var r = foo(1, ''); // r used to be {}, now this is an error
```
添加约束:
```typescript
-interface Animal { x }
-interface Giraffe extends Animal { y }
-interface Elephant extends Animal { z }
-function f(x: T, y: T): T { return undefined; }
+interface Animal {
+ x;
+}
+interface Giraffe extends Animal {
+ y;
+}
+interface Elephant extends Animal {
+ z;
+}
+function f(x: T, y: T): T {
+ return undefined;
+}
var g: Giraffe;
var e: Elephant;
f(g, e);
@@ -51,17 +59,19 @@ f(g, e);
**推荐** 如果这种不匹配的行为是故意为之,那么明确指定类型参数:
```typescript
-var r = foo<{}>(1, ""); // Emulates 1.0 behavior
-var r = foo(1, ""); // Most useful
-var r = foo(1, ""); // Easiest
+var r = foo<{}>(1, ''); // Emulates 1.0 behavior
+var r = foo(1, ''); // Most useful
+var r = foo(1, ''); // Easiest
f(g, e);
```
-_或_重写函数定义指明就算不匹配也没问题:
+*或*重写函数定义指明就算不匹配也没问题:
```typescript
-declare function foo(x: T, y:U): T|U;
-function f(x: T, y: U): T|U { return undefined; }
+declare function foo(x: T, y: U): T | U;
+function f(x: T, y: U): T | U {
+ return undefined;
+}
```
## 泛型剩余参数
@@ -69,48 +79,52 @@ function f(x: T, y: U): T|U { return undefin
不能再使用混杂的参数类型:
```typescript
-function makeArray(...items: T[]): T[] { return items; }
-var r = makeArray(1, ""); // used to return {}[], now an error
+function makeArray(...items: T[]): T[] {
+ return items;
+}
+var r = makeArray(1, ''); // used to return {}[], now an error
```
`new Array(...)`也一样
-**推荐** 声明向后兼容的签名,如果1.0的行为是你想要的:
+**推荐** 声明向后兼容的签名,如果 1.0 的行为是你想要的:
```typescript
function makeArray(...items: T[]): T[];
function makeArray(...items: {}[]): {}[];
-function makeArray(...items: T[]): T[] { return items; }
+function makeArray(...items: T[]): T[] {
+ return items;
+}
```
## 带类型参数接口的重载解析
```typescript
var f10: (x: T, b: () => (a: T) => void, y: T) => T;
-var r9 = f10('', () => (a => a.foo), 1); // r9 was any, now this is an error
+var r9 = f10('', () => a => a.foo, 1); // r9 was any, now this is an error
```
**推荐** 手动指定一个类型参数
```typescript
-var r9 = f10('', () => (a => a.foo), 1);
+var r9 = f10('', () => a => a.foo, 1);
```
## 类声明与类型表达式以严格模式解析
-ECMAScript 2015语言规范\(ECMA-262 6th Edition\)指明_ClassDeclaration_和_ClassExpression_使用严格模式。 因此,在解析类声明或类表达式时将使用额外的限制。
+ECMAScript 2015 语言规范\(ECMA-262 6th Edition\)指明*ClassDeclaration*和*ClassExpression*使用严格模式。 因此,在解析类声明或类表达式时将使用额外的限制。
例如:
```typescript
-class implements {} // Invalid: implements is a reserved word in strict mode
+class implements {} // Invalid: implements is a reserved word in strict mode
class C {
- foo(arguments: any) { // Invalid: "arguments" is not allow as a function argument
- var eval = 10; // Invalid: "eval" is not allowed as the left-hand-side expression
- arguments = []; // Invalid: arguments object is immutable
- }
+ foo(arguments: any) {
+ // Invalid: "arguments" is not allow as a function argument
+ var eval = 10; // Invalid: "eval" is not allowed as the left-hand-side expression
+ arguments = []; // Invalid: arguments object is immutable
+ }
}
```
关于严格模式限制的完整列表,请阅读 Annex C - The Strict Mode of ECMAScript of ECMA-262 6th Edition。
-
diff --git a/zh/breaking-changes/typescript-1.5.md b/zh/breaking-changes/typescript-1.5.md
index 896a7b6f..c1bb0842 100644
--- a/zh/breaking-changes/typescript-1.5.md
+++ b/zh/breaking-changes/typescript-1.5.md
@@ -4,13 +4,13 @@
## 不允许在箭头函数里引用`arguments`
-这是为了遵循ES6箭头函数的语义。之前箭头函数里的`arguments`会绑定到箭头函数的参数。参照[ES6规范草稿](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts) 9.2.12,箭头函数不存在`arguments`对象。 从TypeScript 1.5开始,在箭头函数里使用`arguments`会被标记成错误以确保你的代码转成ES6时没语义上的错误。
+这是为了遵循 ES6 箭头函数的语义。之前箭头函数里的`arguments`会绑定到箭头函数的参数。参照[ES6 规范草稿](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts) 9.2.12,箭头函数不存在`arguments`对象。 从 TypeScript 1.5 开始,在箭头函数里使用`arguments`会被标记成错误以确保你的代码转成 ES6 时没语义上的错误。
**例子:**
```typescript
function f() {
- return () => arguments; // Error: The 'arguments' object cannot be referenced in an arrow function.
+ return () => arguments; // Error: The 'arguments' object cannot be referenced in an arrow function.
}
```
@@ -19,26 +19,30 @@ function f() {
```typescript
// 1. 使用带名字的剩余参数
function f() {
- return (...args) => { args; }
+ return (...args) => {
+ args;
+ };
}
// 2. 使用函数表达式
function f() {
- return function(){ arguments; }
+ return function () {
+ arguments;
+ };
}
```
## 内联枚举引用的改动
-对于正常的枚举,在1.5之前,编译器_仅会_内联常量成员,且成员仅在使用字面量初始化时才被当做是常量。这在判断检举值是使用字面量初始化还是表达式时会行为不一致。从TypeScript 1.5开始,所有非const枚举成员都不会被内联。
+对于正常的枚举,在 1.5 之前,编译器*仅会*内联常量成员,且成员仅在使用字面量初始化时才被当做是常量。这在判断检举值是使用字面量初始化还是表达式时会行为不一致。从 TypeScript 1.5 开始,所有非 const 枚举成员都不会被内联。
**例子:**
```typescript
-var x = E.a; // previously inlined as "var x = 1; /*E.a*/"
+var x = E.a; // previously inlined as "var x = 1; /*E.a*/"
enum E {
- a = 1
+ a = 1,
}
```
@@ -46,74 +50,75 @@ enum E {
## 上下文的类型将作用于`super`和括号表达式
-在1.5之前,上下文的类型不会作用于括号表达式内部。这就要求做显示的类型转换,尤其是在_必须_使用括号来进行表达式转换的场合。
+在 1.5 之前,上下文的类型不会作用于括号表达式内部。这就要求做显示的类型转换,尤其是在*必须*使用括号来进行表达式转换的场合。
在下面的例子里,`m`具有上下文的类型,它在之前的版本里是没有的。
```typescript
-var x: SomeType = (n) => ((m) => q);
-var y: SomeType = t ? (m => m.length) : undefined;
+var x: SomeType = n => m => q;
+var y: SomeType = t ? m => m.length : undefined;
class C extends CBase {
- constructor() {
- super({
- method(m) { return m.length; }
- });
- }
+ constructor() {
+ super({
+ method(m) {
+ return m.length;
+ },
+ });
+ }
}
```
更多信息,查看[\#1425](https://github.com/Microsoft/TypeScript/issues/1425)和[\#920](https://github.com/Microsoft/TypeScript/issues/920)。
-## DOM接口的改动
+## DOM 接口的改动
-TypeScript 1.5改进了`lib.d.ts`库里的DOM类型。这是自TypeScript 1.0以来第一次大的改动;为了拥抱标准DOM规范,很多特定于IE的定义被移除了,同时添加了新的类型如Web Audio和触摸事件。
+TypeScript 1.5 改进了`lib.d.ts`库里的 DOM 类型。这是自 TypeScript 1.0 以来第一次大的改动;为了拥抱标准 DOM 规范,很多特定于 IE 的定义被移除了,同时添加了新的类型如 Web Audio 和触摸事件。
**变通方案:**
-你可以使用旧的`lib.d.ts`配合新版本的编译器。你需要在你的工程里引入之前版本的一个拷贝。这里是[本次改动之前的lib.d.ts文件\(TypeScript 1.5-alpha\)](https://github.com/Microsoft/TypeScript/blob/v1.5.0-alpha/bin/lib.d.ts)。
+你可以使用旧的`lib.d.ts`配合新版本的编译器。你需要在你的工程里引入之前版本的一个拷贝。这里是[本次改动之前的 lib.d.ts 文件\(TypeScript 1.5-alpha\)](https://github.com/Microsoft/TypeScript/blob/v1.5.0-alpha/bin/lib.d.ts)。
**变动列表:**
-* 属性`selection`从`Document`类型上移除
-* 属性`clipboardData`从`Window`类型上移除
-* 删除接口`MSEventAttachmentTarget`
-* 属性`onresize`,`disabled`,`uniqueID`,`removeNode`,`fireEvent`,`currentStyle`,`runtimeStyle`从`HTMLElement`类型上移除
-* 属性`url`从`Event`类型上移除
-* 属性`execScript`,`navigate`,`item`从`Window`类型上移除
-* 属性`documentMode`,`parentWindow`,`createEventObject`从`Document`类型上移除
-* 属性`parentWindow`从`HTMLDocument`类型上移除
-* 属性`setCapture`被完全移除
-* 属性`releaseCapture`被完全移除
-* 属性`setAttribute`,`styleFloat`,`pixelLeft`从`CSSStyleDeclaration`类型上移除
-* 属性`selectorText`从`CSSRule`类型上移除
-* `CSSStyleSheet.rules`现在是`CSSRuleList`类型,而非`MSCSSRuleList`
-* `documentElement`现在是`Element`类型,而非`HTMLElement`
-* `Event`具有一个新的必需属性`returnValue`
-* `Node`具有一个新的必需属性`baseURI`
-* `Element`具有一个新的必需属性`classList`
-* `Location`具有一个新的必需属性`origin`
-* 属性`MSPOINTER_TYPE_MOUSE`,`MSPOINTER_TYPE_TOUCH`从`MSPointerEvent`类型上移除
-* `CSSStyleRule`具有一个新的必需属性`readonly`
-* 属性`execUnsafeLocalFunction`从`MSApp`类型上移除
-* 全局方法`toStaticHTML`被移除
-* `HTMLCanvasElement.getContext`现在返回`CanvasRenderingContext2D | WebGLRenderingContex`
-* 移除扩展类型`Dataview`,`Weakmap`,`Map`,`Set`
-* `XMLHttpRequest.send`具有两个重载`send(data?: Document): void;`和`send(data?: String): void;`
-* `window.orientation`现在是`string`类型,而非`number`
-* 特定于IE的`attachEvent`和`detachEvent`从`Window`上移除
-
-**以下是被新加的DOM类型所部分或全部取代的代码库的代表:**
-
-* `DefinitelyTyped/auth0/auth0.d.ts`
-* `DefinitelyTyped/gamepad/gamepad.d.ts`
-* `DefinitelyTyped/interactjs/interact.d.ts`
-* `DefinitelyTyped/webaudioapi/waa.d.ts`
-* `DefinitelyTyped/webcrypto/WebCrypto.d.ts`
+- 属性`selection`从`Document`类型上移除
+- 属性`clipboardData`从`Window`类型上移除
+- 删除接口`MSEventAttachmentTarget`
+- 属性`onresize`,`disabled`,`uniqueID`,`removeNode`,`fireEvent`,`currentStyle`,`runtimeStyle`从`HTMLElement`类型上移除
+- 属性`url`从`Event`类型上移除
+- 属性`execScript`,`navigate`,`item`从`Window`类型上移除
+- 属性`documentMode`,`parentWindow`,`createEventObject`从`Document`类型上移除
+- 属性`parentWindow`从`HTMLDocument`类型上移除
+- 属性`setCapture`被完全移除
+- 属性`releaseCapture`被完全移除
+- 属性`setAttribute`,`styleFloat`,`pixelLeft`从`CSSStyleDeclaration`类型上移除
+- 属性`selectorText`从`CSSRule`类型上移除
+- `CSSStyleSheet.rules`现在是`CSSRuleList`类型,而非`MSCSSRuleList`
+- `documentElement`现在是`Element`类型,而非`HTMLElement`
+- `Event`具有一个新的必需属性`returnValue`
+- `Node`具有一个新的必需属性`baseURI`
+- `Element`具有一个新的必需属性`classList`
+- `Location`具有一个新的必需属性`origin`
+- 属性`MSPOINTER_TYPE_MOUSE`,`MSPOINTER_TYPE_TOUCH`从`MSPointerEvent`类型上移除
+- `CSSStyleRule`具有一个新的必需属性`readonly`
+- 属性`execUnsafeLocalFunction`从`MSApp`类型上移除
+- 全局方法`toStaticHTML`被移除
+- `HTMLCanvasElement.getContext`现在返回`CanvasRenderingContext2D | WebGLRenderingContex`
+- 移除扩展类型`Dataview`,`Weakmap`,`Map`,`Set`
+- `XMLHttpRequest.send`具有两个重载`send(data?: Document): void;`和`send(data?: String): void;`
+- `window.orientation`现在是`string`类型,而非`number`
+- 特定于 IE 的`attachEvent`和`detachEvent`从`Window`上移除
+
+**以下是被新加的 DOM 类型所部分或全部取代的代码库的代表:**
+
+- `DefinitelyTyped/auth0/auth0.d.ts`
+- `DefinitelyTyped/gamepad/gamepad.d.ts`
+- `DefinitelyTyped/interactjs/interact.d.ts`
+- `DefinitelyTyped/webaudioapi/waa.d.ts`
+- `DefinitelyTyped/webcrypto/WebCrypto.d.ts`
更多信息,查看[完整改动](https://github.com/Microsoft/TypeScript/pull/2739)。
## 类代码体将以严格格式解析
-按照[ES6规范](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code),类代码体现在以严格模式进行解析。行为将相当于在类作用域顶端定义了`"use strict"`;它包括限制了把`arguments`和`eval`做为变量名或参数名的使用,把未来保留字做为变量或参数使用,八进制数字字面量的使用等。
-
+按照[ES6 规范](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code),类代码体现在以严格模式进行解析。行为将相当于在类作用域顶端定义了`"use strict"`;它包括限制了把`arguments`和`eval`做为变量名或参数名的使用,把未来保留字做为变量或参数使用,八进制数字字面量的使用等。
diff --git a/zh/breaking-changes/typescript-1.6.md b/zh/breaking-changes/typescript-1.6.md
index bc4d8a6f..ed6b7948 100644
--- a/zh/breaking-changes/typescript-1.6.md
+++ b/zh/breaking-changes/typescript-1.6.md
@@ -12,10 +12,10 @@
```typescript
var x: { foo: number };
-x = { foo: 1, baz: 2 }; // Error, excess property `baz`
+x = { foo: 1, baz: 2 }; // Error, excess property `baz`
-var y: { foo: number, bar?: number };
-y = { foo: 1, baz: 2 }; // Error, excess or misspelled property `baz`
+var y: { foo: number; bar?: number };
+y = { foo: 1, baz: 2 }; // Error, excess or misspelled property `baz`
```
**推荐:**
@@ -25,17 +25,18 @@ y = { foo: 1, baz: 2 }; // Error, excess or misspelled property `baz`
**如果目标类型接收额外的属性,可以增加一个索引:**
```typescript
-var x: { foo: number, [x: string]: any };
-x = { foo: 1, baz: 2 }; // OK, `baz` matched by index signature
+var x: { foo: number; [x: string]: any };
+x = { foo: 1, baz: 2 }; // OK, `baz` matched by index signature
```
**如果原始类型是一组相关联的类型,使用联合类型明确指定它们的类型而不是仅指定一个基本类型。**
```typescript
-let animalList: (Dog | Cat | Turkey)[] = [ // use union type instead of Animal
- {name: "Milo", meow: true },
- {name: "Pepper", bark: true},
- {name: "koko", gobble: true}
+let animalList: (Dog | Cat | Turkey)[] = [
+ // use union type instead of Animal
+ { name: 'Milo', meow: true },
+ { name: 'Pepper', bark: true },
+ { name: 'koko', gobble: true },
];
```
@@ -43,21 +44,21 @@ let animalList: (Dog | Cat | Turkey)[] = [ // use union type instead of Anima
```typescript
interface Foo {
- foo: number;
+ foo: number;
}
interface FooBar {
- foo: number;
- bar: number;
+ foo: number;
+ bar: number;
}
var y: Foo;
y = { foo: 1, bar: 2 };
```
-## CommonJS的模块解析不再假设路径为相对的
+## CommonJS 的模块解析不再假设路径为相对的
之前,对于`one.ts`和`two.ts`文件,如果它们在相同目录里,那么在`two.ts`里面导入`"one"`时是相对于`one.ts`的路径的。
-TypeScript 1.6在编译CommonJS时,`"one"`不再等同于"./one"。取而代之的是会相对于合适的`node_modules`文件夹进行查找,与Node.js在运行时解析模块相似。更多详情,阅读[the issue that describes the resolution algorithm](https://github.com/Microsoft/TypeScript/issues/2338)。
+TypeScript 1.6 在编译 CommonJS 时,`"one"`不再等同于"./one"。取而代之的是会相对于合适的`node_modules`文件夹进行查找,与 Node.js 在运行时解析模块相似。更多详情,阅读[the issue that describes the resolution algorithm](https://github.com/Microsoft/TypeScript/issues/2338)。
**例子:**
@@ -65,14 +66,14 @@ TypeScript 1.6在编译CommonJS时,`"one"`不再等同于"./one"。取而代
```typescript
export function f() {
- return 10;
+ return 10;
}
```
`./two.ts`
```typescript
-import { f as g } from "one";
+import { f as g } from 'one';
```
**推荐:**
@@ -83,14 +84,14 @@ import { f as g } from "one";
```typescript
export function f() {
- return 10;
+ return 10;
}
```
`./two.ts`
```typescript
-import { f as g } from "./one";
+import { f as g } from './one';
```
**将`--moduleResolution`编译器选项设置为`classic`。**
@@ -100,11 +101,10 @@ import { f as g } from "./one";
在同一空间内默认导出声明的名字与空间内一实体名相同时会得到一个错误;比如,
```typescript
-export default function foo() {
-}
+export default function foo() {}
namespace foo {
- var x = 100;
+ var x = 100;
}
```
@@ -112,11 +112,11 @@ namespace foo {
```typescript
export default class Foo {
- a: number;
+ a: number;
}
interface Foo {
- b: string;
+ b: string;
}
```
@@ -125,11 +125,9 @@ interface Foo {
然而,在下面的例子里合并是被允许的,因为命名空间并不具备做为值的意义:
```typescript
-export default class Foo {
-}
+export default class Foo {}
-namespace Foo {
-}
+namespace Foo {}
```
**推荐:**
@@ -138,11 +136,11 @@ namespace Foo {
```typescript
class Foo {
- a: number;
+ a: number;
}
interface foo {
- b: string;
+ b: string;
}
export default Foo;
@@ -152,29 +150,28 @@ export default Foo;
## 模块体以严格模式解析
-按照[ES6规范](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code),模块体现在以严格模式进行解析。行为将相当于在模块作用域顶端定义了`"use strict"`;它包括限制了把`arguments`和`eval`做为变量名或参数名的使用,把未来保留字做为变量或参数使用,八进制数字字面量的使用等。
+按照[ES6 规范](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code),模块体现在以严格模式进行解析。行为将相当于在模块作用域顶端定义了`"use strict"`;它包括限制了把`arguments`和`eval`做为变量名或参数名的使用,把未来保留字做为变量或参数使用,八进制数字字面量的使用等。
-## 标准库里DOM API的改动
+## 标准库里 DOM API 的改动
-* **MessageEvent**和**ProgressEvent**构造函数希望传入参数;查看[issue \#4295](https://github.com/Microsoft/TypeScript/issues/4295)。
-* **ImageData**构造函数希望传入参数;查看[issue \#4220](https://github.com/Microsoft/TypeScript/issues/4220)。
-* **File**构造函数希望传入参数;查看[issue \#3999](https://github.com/Microsoft/TypeScript/issues/3999)。
+- **MessageEvent**和**ProgressEvent**构造函数希望传入参数;查看[issue \#4295](https://github.com/Microsoft/TypeScript/issues/4295)。
+- **ImageData**构造函数希望传入参数;查看[issue \#4220](https://github.com/Microsoft/TypeScript/issues/4220)。
+- **File**构造函数希望传入参数;查看[issue \#3999](https://github.com/Microsoft/TypeScript/issues/3999)。
## 系统模块输出使用批量导出
-编译器以系统模块的格式使用新的`_export`函数[批量导出](https://github.com/ModuleLoader/es6-module-loader/issues/386)的变体,它接收任何包含键值对的对象做为参数而不是key, value。
+编译器以系统模块的格式使用新的`_export`函数[批量导出](https://github.com/ModuleLoader/es6-module-loader/issues/386)的变体,它接收任何包含键值对的对象做为参数而不是 key, value。
模块加载器需要升级到[v0.17.1](https://github.com/ModuleLoader/es6-module-loader/releases/tag/v0.17.1)或更高。
-## npm包的.js内容从'bin'移到了'lib'
+## npm 包的.js 内容从'bin'移到了'lib'
-TypeScript的npm包入口位置从`bin`移动到了`lib`,以防‘node\_modules/typescript/bin/typescript.js’通过IIS访问的时候造成阻塞(`bin`默认是隐藏段因此IIS会阻止访问这个文件夹)。
+TypeScript 的 npm 包入口位置从`bin`移动到了`lib`,以防‘node_modules/typescript/bin/typescript.js’通过 IIS 访问的时候造成阻塞(`bin`默认是隐藏段因此 IIS 会阻止访问这个文件夹)。
-## TypeScript的npm包不会默认全局安装
+## TypeScript 的 npm 包不会默认全局安装
-TypeScript 1.6从package.json里移除了`preferGlobal`标记。如果你依赖于这种行为,请使用`npm install -g typescript`。
+TypeScript 1.6 从 package.json 里移除了`preferGlobal`标记。如果你依赖于这种行为,请使用`npm install -g typescript`。
## 装饰器做为调用表达式进行检查
-从1.6开始,装饰器类型检查更准确了;编译器会将装饰器表达式做为以被装饰的实体做为参数的调用表达式来进行检查。这可能会造成以前的代码报错。
-
+从 1.6 开始,装饰器类型检查更准确了;编译器会将装饰器表达式做为以被装饰的实体做为参数的调用表达式来进行检查。这可能会造成以前的代码报错。
diff --git a/zh/breaking-changes/typescript-1.7.md b/zh/breaking-changes/typescript-1.7.md
index 0a4aab41..3b5b22ed 100644
--- a/zh/breaking-changes/typescript-1.7.md
+++ b/zh/breaking-changes/typescript-1.7.md
@@ -10,14 +10,14 @@
```typescript
class Fighter {
- /** @returns the winner of the fight. */
- fight(opponent: Fighter) {
- let theVeryBest = this;
- if (Math.rand() < 0.5) {
- theVeryBest = opponent; // error
- }
- return theVeryBest
+ /** @returns the winner of the fight. */
+ fight(opponent: Fighter) {
+ let theVeryBest = this;
+ if (Math.rand() < 0.5) {
+ theVeryBest = opponent; // error
}
+ return theVeryBest;
+ }
}
```
@@ -27,20 +27,20 @@ class Fighter {
```typescript
class Fighter {
- /** @returns the winner of the fight. */
- fight(opponent: Fighter) {
- let theVeryBest: Fighter = this;
- if (Math.rand() < 0.5) {
- theVeryBest = opponent; // no error
- }
- return theVeryBest
+ /** @returns the winner of the fight. */
+ fight(opponent: Fighter) {
+ let theVeryBest: Fighter = this;
+ if (Math.rand() < 0.5) {
+ theVeryBest = opponent; // no error
}
+ return theVeryBest;
+ }
}
```
## 类成员修饰符后面会自动插入分号
-关键字`abstract,public,protected`和`private`是ECMAScript 3里的_保留关键字_并适用于自动插入分号机制。 之前,在这些关键字出现的行尾,TypeScript是不会插入分号的。 现在,这已经被改正了,在上例中`abstract class D`不再能够正确地继承`C`了,而是声明了一个`m`方法和一个额外的属性`abstract`。
+关键字`abstract,public,protected`和`private`是 ECMAScript 3 里的*保留关键字*并适用于自动插入分号机制。 之前,在这些关键字出现的行尾,TypeScript 是不会插入分号的。 现在,这已经被改正了,在上例中`abstract class D`不再能够正确地继承`C`了,而是声明了一个`m`方法和一个额外的属性`abstract`。
注意,`async`和`declare`已经能够正确自动插入分号了。
@@ -48,15 +48,14 @@ class Fighter {
```typescript
abstract class C {
- abstract m(): number;
+ abstract m(): number;
}
abstract class D extends C {
- abstract
- m(): number;
+ abstract;
+ m(): number;
}
```
**推荐:**
在定义类成员时删除关键字后面的换行。通常来讲,要避免依赖于自动插入分号机制。
-
diff --git a/zh/breaking-changes/typescript-1.8.md b/zh/breaking-changes/typescript-1.8.md
index 32be263f..036adbbf 100644
--- a/zh/breaking-changes/typescript-1.8.md
+++ b/zh/breaking-changes/typescript-1.8.md
@@ -128,4 +128,3 @@ class D extends B {
}
}
```
-
diff --git a/zh/breaking-changes/typescript-2.0.md b/zh/breaking-changes/typescript-2.0.md
index a87f3c14..1cdb4dae 100644
--- a/zh/breaking-changes/typescript-2.0.md
+++ b/zh/breaking-changes/typescript-2.0.md
@@ -4,27 +4,27 @@
## 对函数或类表达式的捕获变量不进行类型细化\(narrowing\)
-类型细化不会在函数,类和lambda表达式上进行。
+类型细化不会在函数,类和 lambda 表达式上进行。
**例子**
```typescript
var x: number | string;
-if (typeof x === "number") {
- function inner(): number {
- return x; // Error, type of x is not narrowed, c is number | string
- }
- var y: number = x; // OK, x is number
+if (typeof x === 'number') {
+ function inner(): number {
+ return x; // Error, type of x is not narrowed, c is number | string
+ }
+ var y: number = x; // OK, x is number
}
```
编译器不知道回调函数什么时候被执行。考虑下面的情况:
```typescript
-var x: number | string = "a";
-if (typeof x === "string") {
- setTimeout(() => console.log(x.charAt(0)), 0);
+var x: number | string = 'a';
+if (typeof x === 'string') {
+ setTimeout(() => console.log(x.charAt(0)), 0);
}
x = 5;
```
@@ -36,9 +36,9 @@ x = 5;
使用常量代替:
```typescript
-const x: number | string = "a";
-if (typeof x === "string") {
- setTimeout(() => console.log(x.charAt(0)), 0);
+const x: number | string = 'a';
+if (typeof x === 'string') {
+ setTimeout(() => console.log(x.charAt(0)), 0);
}
```
@@ -48,22 +48,24 @@ if (typeof x === "string") {
```typescript
function g(obj: T) {
- var t: T;
- if (obj instanceof RegExp) {
- t = obj; // RegExp is not assignable to T
- }
+ var t: T;
+ if (obj instanceof RegExp) {
+ t = obj; // RegExp is not assignable to T
+ }
}
```
**推荐** 可以把局部变量声明为特定类型而不是泛型参数或者使用类型断言。
-## 只有get而没有set的存取器会被自动推断为`readonly`属性
+## 只有 get 而没有 set 的存取器会被自动推断为`readonly`属性
**例子**
```typescript
class C {
- get x() { return 0; }
+ get x() {
+ return 0;
+ }
}
var c = new C();
@@ -72,17 +74,17 @@ c.x = 1; // Error Left-hand side is a readonly property
**推荐**
-定义一个不对属性写值的setter。
+定义一个不对属性写值的 setter。
## 在严格模式下函数声明不允许出现在块\(block\)里
-在严格模式下这已经是一个运行时错误。从TypeScript 2.0开始,它会被标记为编译时错误。
+在严格模式下这已经是一个运行时错误。从 TypeScript 2.0 开始,它会被标记为编译时错误。
**例子**
```typescript
-if( true ) {
- function foo() {}
+if (true) {
+ function foo() {}
}
export = foo;
@@ -93,26 +95,25 @@ export = foo;
使用函数表达式代替:
```typescript
-if( true ) {
- const foo = function() {}
+if (true) {
+ const foo = function () {};
}
```
## `TemplateStringsArray`现是是不可变的
-ES2015模版字符串总是将它们的标签以不可变的类数组对象进行传递,这个对象带有一个`raw`属性(同样是不可变的)。 TypeScript把这个对象命名为`TemplateStringsArray`。
+ES2015 模版字符串总是将它们的标签以不可变的类数组对象进行传递,这个对象带有一个`raw`属性(同样是不可变的)。 TypeScript 把这个对象命名为`TemplateStringsArray`。
便利的是,`TemplateStringsArray`可以赋值给`Array`,因此你可以利用这个较短的类型来使用标签参数:
```typescript
function myTemplateTag(strs: string[]) {
- // ...
+ // ...
}
```
-然而,在TypeScript 2.0,支持用`readonly`修饰符表示这些对象是不可变的。 这样的话,`TemplateStringsArray` 就变成了不可变的,并且不再可以赋值给`string[]`。
+然而,在 TypeScript 2.0,支持用`readonly`修饰符表示这些对象是不可变的。 这样的话,`TemplateStringsArray` 就变成了不可变的,并且不再可以赋值给`string[]`。
**推荐**
直接使用`TemplateStringsArray`(或者使用`ReadonlyArray`)。
-
diff --git a/zh/breaking-changes/typescript-2.1.md b/zh/breaking-changes/typescript-2.1.md
index 1aff79d5..6a00cc10 100644
--- a/zh/breaking-changes/typescript-2.1.md
+++ b/zh/breaking-changes/typescript-2.1.md
@@ -4,7 +4,7 @@
## 生成的构造函数代码将`this`的值替换为`super(...)`调用的返回值
-在ES2015中,如果构造函数返回一个对象,那么对于任何`super(...)`的调用者将隐式地替换掉`this`的值。 因此,有必要获取任何可能的`super(...)`的返回值并用`this`进行替换。
+在 ES2015 中,如果构造函数返回一个对象,那么对于任何`super(...)`的调用者将隐式地替换掉`this`的值。 因此,有必要获取任何可能的`super(...)`的返回值并用`this`进行替换。
**示例**
@@ -12,11 +12,11 @@
```typescript
class C extends B {
- public a: number;
- constructor() {
- super();
- this.a = 0;
- }
+ public a: number;
+ constructor() {
+ super();
+ this.a = 0;
+ }
}
```
@@ -24,27 +24,27 @@ class C extends B {
```javascript
var C = (function (_super) {
- __extends(C, _super);
- function C() {
- var _this = _super.call(this) || this;
- _this.a = 0;
- return _this;
- }
- return C;
-}(B));
+ __extends(C, _super);
+ function C() {
+ var _this = _super.call(this) || this;
+ _this.a = 0;
+ return _this;
+ }
+ return C;
+})(B);
```
注意:
-* `_super.call(this)`存入局部变量`_this`
-* 构造函数体里所有使用`this`的地方都被替换为`super`调用的返回值(例如`_this`)
-* 每个构造函数将明确地返回它的`this`,以确保正确的继承
+- `_super.call(this)`存入局部变量`_this`
+- 构造函数体里所有使用`this`的地方都被替换为`super`调用的返回值(例如`_this`)
+- 每个构造函数将明确地返回它的`this`,以确保正确的继承
值得注意的是在`super(...)`调用前就使用`this`从[TypeScript 1.8](typescript-2.1.md#disallow-this-accessing-before-super-call)开始将会引发错误。
## 继承内置类型如`Error`,`Array`和`Map`将是无效的
-做为将`this`的值替换为`super(...)`调用返回值的一部分,子类化`Error`,`Array`等的结果可以是非预料的。 这是因为`Error`,`Array`等的构造函数会使用ECMAScript 6的`new.target`来调整它们的原型链; 然而,在ECMAScript 5中调用构造函数时却没有有效的方法来确保`new.target`的值。 在默认情况下,其它低级别的编译器也普遍存在这个限制。
+做为将`this`的值替换为`super(...)`调用返回值的一部分,子类化`Error`,`Array`等的结果可以是非预料的。 这是因为`Error`,`Array`等的构造函数会使用 ECMAScript 6 的`new.target`来调整它们的原型链; 然而,在 ECMAScript 5 中调用构造函数时却没有有效的方法来确保`new.target`的值。 在默认情况下,其它低级别的编译器也普遍存在这个限制。
**示例**
@@ -52,19 +52,19 @@ var C = (function (_super) {
```typescript
class FooError extends Error {
- constructor(m: string) {
- super(m);
- }
- sayHello() {
- return "hello " + this.message;
- }
+ constructor(m: string) {
+ super(m);
+ }
+ sayHello() {
+ return 'hello ' + this.message;
+ }
}
```
你会发现:
-* 由这个子类构造出来的对象上的方法可能为`undefined`,因此调用`sayHello`会引发错误。
-* `instanceof`应用于子类与其实例之前会失效,因此`(new FooError()) instanceof FooError`会返回`false`。
+- 由这个子类构造出来的对象上的方法可能为`undefined`,因此调用`sayHello`会引发错误。
+- `instanceof`应用于子类与其实例之前会失效,因此`(new FooError()) instanceof FooError`会返回`false`。
**推荐**
@@ -72,22 +72,22 @@ class FooError extends Error {
```typescript
class FooError extends Error {
- constructor(m: string) {
- super(m);
+ constructor(m: string) {
+ super(m);
- // Set the prototype explicitly.
- Object.setPrototypeOf(this, FooError.prototype);
- }
+ // Set the prototype explicitly.
+ Object.setPrototypeOf(this, FooError.prototype);
+ }
- sayHello() {
- return "hello " + this.message;
- }
+ sayHello() {
+ return 'hello ' + this.message;
+ }
}
```
但是,任何`FooError`的子类也必须要手动地设置原型。 对于那些不支持[`Object.setPrototypeOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)的运行时环境,你可以使用[`__proto__`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto)。
-不幸的是,\[这些变通方法在IE10及其之前的版本\]\([https://msdn.microsoft.com/en-us/library/s4esdbwz\(v=vs.94\).aspx](https://msdn.microsoft.com/en-us/library/s4esdbwz%28v=vs.94%29.aspx)\) 你可以手动地将方法从原型上拷贝到实例上(比如从`FooError.prototype`到`this`),但是原型链却是无法修复的。
+不幸的是,\[这些变通方法在 IE10 及其之前的版本\]\([https://msdn.microsoft.com/en-us/library/s4esdbwz\(v=vs.94\).aspx](https://msdn.microsoft.com/en-us/library/s4esdbwz%28v=vs.94%29.aspx)\) 你可以手动地将方法从原型上拷贝到实例上(比如从`FooError.prototype`到`this`),但是原型链却是无法修复的。
## `const`变量和`readonly`属性会默认地推断成字面类型
@@ -120,7 +120,7 @@ const DEBUG = true; // `boolean`类型
```typescript
declare function push(...args: T[]): T;
-var x = push("A", "B", "C"); // 推断成 "A" | "B" | "C" 在TS 2.1, 在TS 2.0里为 string
+var x = push('A', 'B', 'C'); // 推断成 "A" | "B" | "C" 在TS 2.1, 在TS 2.0里为 string
```
**推荐**
@@ -128,12 +128,12 @@ var x = push("A", "B", "C"); // 推断成 "A" | "B" | "C" 在TS 2.1, 在TS 2.0
在调用处明确指定参数类型:
```typescript
-var x = push("A", "B", "C"); // x是string
+var x = push('A', 'B', 'C'); // x是string
```
-## 没有注解的callback参数如果没有与之匹配的重载参数会触发implicit-any错误
+## 没有注解的 callback 参数如果没有与之匹配的重载参数会触发 implicit-any 错误
-在之前编译器默默地赋予callback(下面的`c`)的参数一个`any`类型。原因关乎到编译器如何解析重载的函数表达式。从TypeScript 2.1开始,在使用`--noImplicitAny`时,这会触发一个错误。
+在之前编译器默默地赋予 callback(下面的`c`)的参数一个`any`类型。原因关乎到编译器如何解析重载的函数表达式。从 TypeScript 2.1 开始,在使用`--noImplicitAny`时,这会触发一个错误。
**示例**
@@ -141,24 +141,24 @@ var x = push("A", "B", "C"); // x是string
declare function func(callback: () => void): any;
declare function func(callback: (arg: number) => void): any;
-func(c => { });
+func(c => {});
```
**推荐**
-删除第一个重载,因为它实在没什么意义;上面的函数可以使用1个或0个必须参数调用,因为函数可以安全地忽略额外的参数。
+删除第一个重载,因为它实在没什么意义;上面的函数可以使用 1 个或 0 个必须参数调用,因为函数可以安全地忽略额外的参数。
```typescript
declare function func(callback: (arg: number) => void): any;
-func(c => { });
-func(() => { });
+func(c => {});
+func(() => {});
```
-或者,你可以给callback的参数指定一个明确的类型:
+或者,你可以给 callback 的参数指定一个明确的类型:
```typescript
-func((c:number) => { });
+func((c: number) => {});
```
## 逗号操作符使用在无副作用的表达式里时会被标记成错误
@@ -172,8 +172,8 @@ let x = Math.pow((3, 5)); // x = NaN, was meant to be `Math.pow(3, 5)`
// This code does not do what it appears to!
let arr = [];
-switch(arr.length) {
- case 0, 1:
+switch (arr.length) {
+ case (0, 1):
return 'zero or one';
default:
return 'more than one';
@@ -189,11 +189,10 @@ let a = 0;
let y = (void a, 1); // no warning for `a`
```
-## 标准库里的DOM API变动
+## 标准库里的 DOM API 变动
-* **Node.firstChild**,**Node.lastChild**,**Node.nextSibling**,**Node.previousSibling**,**Node.parentElement**和**Node.parentNode**现在是`Node | null`而非`Node`。
+- **Node.firstChild**,**Node.lastChild**,**Node.nextSibling**,**Node.previousSibling**,**Node.parentElement**和**Node.parentNode**现在是`Node | null`而非`Node`。
查看[\#11113](https://github.com/Microsoft/TypeScript/issues/11113)了解详细信息。
推荐明确检查`null`或使用`!`断言操作符(比如`node.lastChild!`)。
-
diff --git a/zh/breaking-changes/typescript-2.2.md b/zh/breaking-changes/typescript-2.2.md
index 75671b3a..3369fa6b 100644
--- a/zh/breaking-changes/typescript-2.2.md
+++ b/zh/breaking-changes/typescript-2.2.md
@@ -2,8 +2,7 @@
完整的破坏性改动列表请到这里查看:[breaking change issues](https://github.com/Microsoft/TypeScript/issues?q=is%3Aissue+milestone%3A%22TypeScript+2.2%22+label%3A%22Breaking+Change%22+is%3Aclosed).
-## 标准库里的DOM API变动
-
-* 现在标准库里有`Window.fetch`的声明;仍依赖于`@types\whatwg-fetch`会产生声明冲突错误,需要被移除。
-* 现在标准库里有`ServiceWorker`的声明;仍依赖于`@types\service_worker_api`会产生声明冲突错误,需要被移除。
+## 标准库里的 DOM API 变动
+- 现在标准库里有`Window.fetch`的声明;仍依赖于`@types\whatwg-fetch`会产生声明冲突错误,需要被移除。
+- 现在标准库里有`ServiceWorker`的声明;仍依赖于`@types\service_worker_api`会产生声明冲突错误,需要被移除。
diff --git a/zh/breaking-changes/typescript-2.3.md b/zh/breaking-changes/typescript-2.3.md
index 3f306ed8..524ce71b 100644
--- a/zh/breaking-changes/typescript-2.3.md
+++ b/zh/breaking-changes/typescript-2.3.md
@@ -7,8 +7,7 @@
**示例**
```typescript
-class X<> {} // Error: Type parameter list cannot be empty.
-function f<>() {} // Error: Type parameter list cannot be empty.
-const x: X<> = new X<>(); // Error: Type parameter list cannot be empty.
+class X<> {} // Error: Type parameter list cannot be empty.
+function f<>() {} // Error: Type parameter list cannot be empty.
+const x: X<> = new X<>(); // Error: Type parameter list cannot be empty.
```
-
diff --git a/zh/breaking-changes/typescript-2.4.md b/zh/breaking-changes/typescript-2.4.md
index ed1a69ad..fb2e57b6 100644
--- a/zh/breaking-changes/typescript-2.4.md
+++ b/zh/breaking-changes/typescript-2.4.md
@@ -4,13 +4,13 @@
## 弱类型检测
-TypeScript 2.4引入了“弱类型(weak type)”的概念。 若一个类型只包含可选的属性,那么它就被认为是_弱(weak)_的。 例如,下面的`Options`类型就是一个弱类型:
+TypeScript 2.4 引入了“弱类型(weak type)”的概念。 若一个类型只包含可选的属性,那么它就被认为是*弱(weak)*的。 例如,下面的`Options`类型就是一个弱类型:
```typescript
interface Options {
- data?: string,
- timeout?: number,
- maxRetries?: number,
+ data?: string;
+ timeout?: number;
+ maxRetries?: number;
}
```
@@ -18,13 +18,13 @@ TypeScript 2.4,当给一个弱类型赋值,但是它们之前没有共同的
```typescript
function sendMessage(options: Options) {
- // ...
+ // ...
}
const opts = {
- payload: "hello world!",
- retryOnFail: true,
-}
+ payload: 'hello world!',
+ retryOnFail: true,
+};
// 错误!
sendMessage(opts);
@@ -40,22 +40,22 @@ sendMessage(opts);
## 推断返回值的类型
-TypeScript现在可从上下文类型中推断出一个调用的返回值类型。 这意味着一些代码现在会适当地报错。 下面是一个例子:
+TypeScript 现在可从上下文类型中推断出一个调用的返回值类型。 这意味着一些代码现在会适当地报错。 下面是一个例子:
```typescript
let x: Promise = new Promise(resolve => {
- resolve(10);
- // ~~ 错误! 'number'类型不能赋值给'string'类型
+ resolve(10);
+ // ~~ 错误! 'number'类型不能赋值给'string'类型
});
```
## 更严格的回调函数参数变化
-TypeScript对回调函数参数的检测将与立即签名检测协变。 之前是双变的,这会导致有时候错误的类型也能通过检测。 根本上讲,这意味着回调函数参数和包含回调的类会被更细致地检查,因此Typescript会要求更严格的类型。 这在Promises和Observables上是十分明显的。
+TypeScript 对回调函数参数的检测将与立即签名检测协变。 之前是双变的,这会导致有时候错误的类型也能通过检测。 根本上讲,这意味着回调函数参数和包含回调的类会被更细致地检查,因此 Typescript 会要求更严格的类型。 这在 Promises 和 Observables 上是十分明显的。
### Promises
-下面是改进后的Promise检查的例子:
+下面是改进后的 Promise 检查的例子:
```typescript
let p = new Promise((c, e) => { c(12) });
@@ -64,19 +64,23 @@ let u: Promise = p;
类型 'Promise<{}>' 不能赋值给 'Promise'
```
-TypeScript无法在调用`new Promise`时推断类型参数`T`的值。 因此,它仅推断为`Promise<{}>`。 不幸的是,它会允许你这样写`c(12)`和`c('foo')`,就算`p`的声明明确指出它应该是`Promise`。
+TypeScript 无法在调用`new Promise`时推断类型参数`T`的值。 因此,它仅推断为`Promise<{}>`。 不幸的是,它会允许你这样写`c(12)`和`c('foo')`,就算`p`的声明明确指出它应该是`Promise`。
-在新的规则下,`Promise<{}>`不能够赋值给`Promise`,因为它破坏了Promise的回调函数。 TypeScript仍无法推断类型参数,所以你只能通过传递类型参数来解决这个问题:
+在新的规则下,`Promise<{}>`不能够赋值给`Promise`,因为它破坏了 Promise 的回调函数。 TypeScript 仍无法推断类型参数,所以你只能通过传递类型参数来解决这个问题:
```typescript
-let p: Promise = new Promise((c, e) => { c(12) });
+let p: Promise = new Promise((c, e) => {
+ c(12);
+});
// ^^^^^^^^ 明确的类型参数
```
-它能够帮助从promise代码体里发现错误。 现在,如果你错误地调用`c('foo')`,你就会得到一个错误提示:
+它能够帮助从 promise 代码体里发现错误。 现在,如果你错误地调用`c('foo')`,你就会得到一个错误提示:
```typescript
-let p: Promise = new Promise((c, e) => { c('foo') });
+let p: Promise = new Promise((c, e) => {
+ c('foo');
+});
// ~~~~~
// 参数类型 '"foo"' 不能赋值给 'number'
```
@@ -98,20 +102,20 @@ f((nested: (error: number) => void) => { log(error) });
修复这个问题很容易。给嵌套的回调传入缺失的参数:
```typescript
-f((nested: (error: number, result: any) => void) => { });
+f((nested: (error: number, result: any) => void) => {});
```
## 更严格的泛型函数检查
-TypeScript在比较两个单一签名的类型时会尝试统一类型参数。 结果就是,当关系到两个泛型签名时检查变得更严格了,但同时也会捕获一些bug。
+TypeScript 在比较两个单一签名的类型时会尝试统一类型参数。 结果就是,当关系到两个泛型签名时检查变得更严格了,但同时也会捕获一些 bug。
```typescript
type A = (x: T, y: U) => [T, U];
type B = (x: S, y: S) => [S, S];
function f(a: A, b: B) {
- a = b; // Error
- b = a; // Ok
+ a = b; // Error
+ b = a; // Ok
}
```
@@ -121,7 +125,7 @@ function f(a: A, b: B) {
## 从上下文类型中推荐类型参数
-在TypeScript之前,下面例子中
+在 TypeScript 之前,下面例子中
```typescript
let f: (x: T) => T = y => y;
@@ -136,4 +140,3 @@ let f: (x: T) => T = y => y() + y.foo.bar;
**推荐做法:**
适当地重新审视你的泛型是否为正确的约束。实在不行,就为参数加上`any`注解。
-
diff --git a/zh/breaking-changes/typescript-2.6.md b/zh/breaking-changes/typescript-2.6.md
index 4b4f81fe..187b67d6 100644
--- a/zh/breaking-changes/typescript-2.6.md
+++ b/zh/breaking-changes/typescript-2.6.md
@@ -8,24 +8,24 @@
```typescript
function f(n: number) {
- n = 0;
+ n = 0;
}
class C {
- private m: number;
- constructor() {
- this.m = 0;
- }
+ private m: number;
+ constructor() {
+ this.m = 0;
+ }
}
```
-现在,当启用`--noUnusedLocals`和`--noUnusedParameters`[编译器选项](https://www.typescriptlang.org/docs/handbook/compiler-options.html)时,`n`和`m`都将被标记为未使用,因为它们的值永远不会被_读_ 。以前TypeScript只会检查它们的值是否被_引用_。
+现在,当启用`--noUnusedLocals`和`--noUnusedParameters`[编译器选项](https://www.typescriptlang.org/docs/handbook/compiler-options.html)时,`n`和`m`都将被标记为未使用,因为它们的值永远不会被*读* 。以前 TypeScript 只会检查它们的值是否被*引用*。
此外,仅在其自己的实体中调用的递归函数被视为未使用。
```typescript
function f() {
- f(); // Error: 'f' is declared but its value is never read
+ f(); // Error: 'f' is declared but its value is never read
}
```
@@ -34,19 +34,18 @@ function f() {
以前,像这样的结构
```typescript
-declare module "foo" {
- export default "some" + "string";
+declare module 'foo' {
+ export default 'some' + 'string';
}
```
-在环境上下文中未被标记为错误。声明文件和环境模块中通常禁止使用表达式,因为`typeof`之类的意图不明确,因此这与我们在这些上下文中的其他地方处理可执行代码不一致。现在,任何不是标识符或限定名称的内容都会被标记为错误。为具有上述值形状的模块制作DTS的正确方法如下:
+在环境上下文中未被标记为错误。声明文件和环境模块中通常禁止使用表达式,因为`typeof`之类的意图不明确,因此这与我们在这些上下文中的其他地方处理可执行代码不一致。现在,任何不是标识符或限定名称的内容都会被标记为错误。为具有上述值形状的模块制作 DTS 的正确方法如下:
```typescript
-declare module "foo" {
- const _default: string;
- export default _default;
+declare module 'foo' {
+ const _default: string;
+ export default _default;
}
```
编译器已经生成了这样的定义,因此这只应该是手工编写的定义的问题。
-
diff --git a/zh/breaking-changes/typescript-2.7.md b/zh/breaking-changes/typescript-2.7.md
index 41ca733f..3842f4e0 100644
--- a/zh/breaking-changes/typescript-2.7.md
+++ b/zh/breaking-changes/typescript-2.7.md
@@ -12,7 +12,7 @@ var triple: [number, number, number] = [1, 2, 3];
pair = triple;
```
-但是,这_是_一个错误:
+但是,这*是*一个错误:
```typescript
triple = pair;
@@ -29,7 +29,7 @@ for (const n of numbers) {
}
```
-对此最好的解决方法是创建扩展Array的自己的类型:
+对此最好的解决方法是创建扩展 Array 的自己的类型:
```typescript
interface Struct extends Array {
@@ -42,9 +42,9 @@ for (const n of numbers) {
}
```
-## 在`allowSyntheticDefaultImports`下,对于TS和JS文件来说默认导入的类型合成不常见
+## 在`allowSyntheticDefaultImports`下,对于 TS 和 JS 文件来说默认导入的类型合成不常见
-在过去,我们在类型系统中合成一个默认导入,用于TS或JS文件,如下所示:
+在过去,我们在类型系统中合成一个默认导入,用于 TS 或 JS 文件,如下所示:
```typescript
export const foo = 12;
@@ -54,31 +54,30 @@ export const foo = 12;
## 更严格地检查索引访问泛型类型约束
-以前,仅当类型具有索引签名时才计算索引访问类型的约束,否则它是`any`。这样就可以取消选中无效赋值。在TS 2.7.1中,编译器在这里有点聪明,并且会将约束计算为此处所有可能属性的并集。
+以前,仅当类型具有索引签名时才计算索引访问类型的约束,否则它是`any`。这样就可以取消选中无效赋值。在 TS 2.7.1 中,编译器在这里有点聪明,并且会将约束计算为此处所有可能属性的并集。
```typescript
interface O {
- foo?: string;
+ foo?: string;
}
function fails(o: O, k: K) {
- var s: string = o[k]; // Previously allowed, now an error
- // string | undefined is not assignable to a string
+ var s: string = o[k]; // Previously allowed, now an error
+ // string | undefined is not assignable to a string
}
```
## `in`表达式被视为类型保护
-对于`n in x`表达式,其中`n`是字符串文字或字符串文字类型而`x`是联合类型,"true"分支缩小为具有可选或必需属性`n`的类型,并且 "false"分支缩小为具有可选或缺少属性`n`的类型。 如果声明类型始终具有属性`n`,则可能导致在false分支中将变量的类型缩小为`never`的情况。
+对于`n in x`表达式,其中`n`是字符串文字或字符串文字类型而`x`是联合类型,"true"分支缩小为具有可选或必需属性`n`的类型,并且 "false"分支缩小为具有可选或缺少属性`n`的类型。 如果声明类型始终具有属性`n`,则可能导致在 false 分支中将变量的类型缩小为`never`的情况。
```typescript
var x: { foo: number };
-if ("foo" in x) {
- x; // { foo: number }
-}
-else {
- x; // never
+if ('foo' in x) {
+ x; // { foo: number }
+} else {
+ x; // never
}
```
@@ -87,12 +86,10 @@ else {
以前在结构上相同的类在条件或`||`运算符中被简化为最佳公共类型。现在这些类以联合类型维护,以便更准确地检查`instanceof`运算符。
```typescript
-class Animal {
-
-}
+class Animal {}
class Dog {
- park() { }
+ park() {}
}
var a = Math.random() ? new Animal() : new Dog();
@@ -104,14 +101,11 @@ var a = Math.random() ? new Animal() : new Dog();
`CustomEvent`现在有一个`details`属性类型的类型参数。如果要从中扩展,则需要指定其他类型参数。
```typescript
-class MyCustomEvent extends CustomEvent {
-}
+class MyCustomEvent extends CustomEvent {}
```
应该成为
```typescript
-class MyCustomEvent extends CustomEvent {
-}
+class MyCustomEvent extends CustomEvent {}
```
-
diff --git a/zh/breaking-changes/typescript-2.8.md b/zh/breaking-changes/typescript-2.8.md
index 59290ab6..9d46b506 100644
--- a/zh/breaking-changes/typescript-2.8.md
+++ b/zh/breaking-changes/typescript-2.8.md
@@ -4,35 +4,34 @@
根据 [\#20568](https://github.com/Microsoft/TypeScript/issues/20568),未使用的类型参数之前在`--noUnusedLocals`下报告,但现在报告在`--noUnusedParameters`下。
-## 从`lib.d.ts`中删除了一些Microsoft 专用的类型
-
-从DOM定义中删除一些Microsoft 专用的类型以更好地与标准对齐。 删除的类型包括:
-
-* `MSApp`
-* `MSAppAsyncOperation`
-* `MSAppAsyncOperationEventMap`
-* `MSBaseReader`
-* `MSBaseReaderEventMap`
-* `MSExecAtPriorityFunctionCallback`
-* `MSHTMLWebViewElement`
-* `MSManipulationEvent`
-* `MSRangeCollection`
-* `MSSiteModeEvent`
-* `MSUnsafeFunctionCallback`
-* `MSWebViewAsyncOperation`
-* `MSWebViewAsyncOperationEventMap`
-* `MSWebViewSettings`
+## 从`lib.d.ts`中删除了一些 Microsoft 专用的类型
+
+从 DOM 定义中删除一些 Microsoft 专用的类型以更好地与标准对齐。 删除的类型包括:
+
+- `MSApp`
+- `MSAppAsyncOperation`
+- `MSAppAsyncOperationEventMap`
+- `MSBaseReader`
+- `MSBaseReaderEventMap`
+- `MSExecAtPriorityFunctionCallback`
+- `MSHTMLWebViewElement`
+- `MSManipulationEvent`
+- `MSRangeCollection`
+- `MSSiteModeEvent`
+- `MSUnsafeFunctionCallback`
+- `MSWebViewAsyncOperation`
+- `MSWebViewAsyncOperationEventMap`
+- `MSWebViewSettings`
## `HTMLObjectElement`不再具有`alt`属性
-根据 [\#21386](https://github.com/Microsoft/TypeScript/issues/21386),DOM库已更新以反映WHATWG标准。
+根据 [\#21386](https://github.com/Microsoft/TypeScript/issues/21386),DOM 库已更新以反映 WHATWG 标准。
如果需要继续使用`alt`属性,请考虑通过全局范围中的接口合并重新打开`HTMLObjectElement`:
```typescript
// Must be in a global .ts file or a 'declare global' block.
interface HTMLObjectElement {
- alt: string;
+ alt: string;
}
```
-
diff --git a/zh/breaking-changes/typescript-2.9.md b/zh/breaking-changes/typescript-2.9.md
index 071bde96..cdecb52f 100644
--- a/zh/breaking-changes/typescript-2.9.md
+++ b/zh/breaking-changes/typescript-2.9.md
@@ -6,21 +6,21 @@ TypeScript 2.9 将索引类型泛化为包括 `number` 和 `symbol` 命名属性
```typescript
function useKey(o: T, k: K) {
- var name: string = k; // 错误: keyof T 不能分配给 `string`
+ var name: string = k; // 错误: keyof T 不能分配给 `string`
}
```
### 建议
-* 如果你的函数只能处理名字符串属性的键,请在声明中使用 `Extract`:
+- 如果你的函数只能处理名字符串属性的键,请在声明中使用 `Extract`:
```typescript
function useKey>(o: T, k: K) {
- var name: string = k; // OK
+ var name: string = k; // OK
}
```
-* 如果你的函数可以处理所有属性键,那么更改应该是顺畅的:
+- 如果你的函数可以处理所有属性键,那么更改应该是顺畅的:
```typescript
function useKey(o: T, k: K) {
@@ -28,17 +28,16 @@ function useKey(o: T, k: K) {
}
```
-* 除此之外,还可以使用 `--keyofStringsOnly` 编译器选项禁用新行为。
+- 除此之外,还可以使用 `--keyofStringsOnly` 编译器选项禁用新行为。
## 剩余参数后面不允许尾后逗号
以下代码是一个自 [\#22262](https://github.com/Microsoft/TypeScript/pull/22262) 开始的编译器错误:
```typescript
-function f(
- a: number,
- ...b: number[], // 违规的尾随逗号
-) {}
+function f(a: number, ...b: number[]) {
+ // 违规的尾随逗号
+}
```
剩余参数上的尾随逗号不是有效的 JavaScript,并且,这个语法现在在 TypeScript 中也是一个错误。
@@ -57,5 +56,4 @@ function f(x: T) {
## 参考
-* [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-29)
-
+- [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-29)
diff --git a/zh/breaking-changes/typescript-3.0.md b/zh/breaking-changes/typescript-3.0.md
index 2d24e703..2fec73ef 100644
--- a/zh/breaking-changes/typescript-3.0.md
+++ b/zh/breaking-changes/typescript-3.0.md
@@ -9,7 +9,7 @@
关闭 `strictNullChecks` 时,下例中 `A` 的类型为 `null`,而 `B` 的类型为 `undefined`:
```typescript
-type A = { a: number } & null; // null
+type A = { a: number } & null; // null
type B = { a: number } & undefined; // undefined
```
@@ -21,5 +21,4 @@ type B = { a: number } & undefined; // undefined
## 参考
-* [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-30)
-
+- [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-30)
diff --git a/zh/breaking-changes/typescript-3.1.md b/zh/breaking-changes/typescript-3.1.md
index 279ced2c..7aad9a0d 100644
--- a/zh/breaking-changes/typescript-3.1.md
+++ b/zh/breaking-changes/typescript-3.1.md
@@ -2,21 +2,173 @@
## 一些浏览器厂商特定的类型从`lib.d.ts`中被移除
-TypeScript内置的`.d.ts`库\(`lib.d.ts`等\)现在会部分地从DOM规范的Web IDL文件中生成。 因此有一些浏览器厂商特定的类型被移除了。
+TypeScript 内置的`.d.ts`库\(`lib.d.ts`等\)现在会部分地从 DOM 规范的 Web IDL 文件中生成。 因此有一些浏览器厂商特定的类型被移除了。
点击这里查看被移除类型的完整列表:
- \* \`CanvasRenderingContext2D.mozImageSmoothingEnabled\` \* \`CanvasRenderingContext2D.msFillRule\` \* \`CanvasRenderingContext2D.oImageSmoothingEnabled\` \* \`CanvasRenderingContext2D.webkitImageSmoothingEnabled\` \* \`Document.caretRangeFromPoint\` \* \`Document.createExpression\` \* \`Document.createNSResolver\` \* \`Document.execCommandShowHelp\` \* \`Document.exitFullscreen\` \* \`Document.exitPointerLock\` \* \`Document.focus\` \* \`Document.fullscreenElement\` \* \`Document.fullscreenEnabled\` \* \`Document.getSelection\` \* \`Document.msCapsLockWarningOff\` \* \`Document.msCSSOMElementFloatMetrics\` \* \`Document.msElementsFromRect\` \* \`Document.msElementsFromPoint\` \* \`Document.onvisibilitychange\` \* \`Document.onwebkitfullscreenchange\` \* \`Document.onwebkitfullscreenerror\` \* \`Document.pointerLockElement\` \* \`Document.queryCommandIndeterm\` \* \`Document.URLUnencoded\` \* \`Document.webkitCurrentFullScreenElement\` \* \`Document.webkitFullscreenElement\` \* \`Document.webkitFullscreenEnabled\` \* \`Document.webkitIsFullScreen\` \* \`Document.xmlEncoding\` \* \`Document.xmlStandalone\` \* \`Document.xmlVersion\` \* \`DocumentType.entities\` \* \`DocumentType.internalSubset\` \* \`DocumentType.notations\` \* \`DOML2DeprecatedSizeProperty\` \* \`Element.msContentZoomFactor\` \* \`Element.msGetUntransformedBounds\` \* \`Element.msMatchesSelector\` \* \`Element.msRegionOverflow\` \* \`Element.msReleasePointerCapture\` \* \`Element.msSetPointerCapture\` \* \`Element.msZoomTo\` \* \`Element.onwebkitfullscreenchange\` \* \`Element.onwebkitfullscreenerror\` \* \`Element.webkitRequestFullScreen\` \* \`Element.webkitRequestFullscreen\` \* \`ElementCSSInlineStyle\` \* \`ExtendableEventInit\` \* \`ExtendableMessageEventInit\` \* \`FetchEventInit\` \* \`GenerateAssertionCallback\` \* \`HTMLAnchorElement.Methods\` \* \`HTMLAnchorElement.mimeType\` \* \`HTMLAnchorElement.nameProp\` \* \`HTMLAnchorElement.protocolLong\` \* \`HTMLAnchorElement.urn\` \* \`HTMLAreasCollection\` \* \`HTMLHeadElement.profile\` \* \`HTMLImageElement.msGetAsCastingSource\` \* \`HTMLImageElement.msGetAsCastingSource\` \* \`HTMLImageElement.msKeySystem\` \* \`HTMLImageElement.msPlayToDisabled\` \* \`HTMLImageElement.msPlayToDisabled\` \* \`HTMLImageElement.msPlayToPreferredSourceUri\` \* \`HTMLImageElement.msPlayToPreferredSourceUri\` \* \`HTMLImageElement.msPlayToPrimary\` \* \`HTMLImageElement.msPlayToPrimary\` \* \`HTMLImageElement.msPlayToSource\` \* \`HTMLImageElement.msPlayToSource\` \* \`HTMLImageElement.x\` \* \`HTMLImageElement.y\` \* \`HTMLInputElement.webkitdirectory\` \* \`HTMLLinkElement.import\` \* \`HTMLMetaElement.charset\` \* \`HTMLMetaElement.url\` \* \`HTMLSourceElement.msKeySystem\` \* \`HTMLStyleElement.disabled\` \* \`HTMLSummaryElement\` \* \`MediaQueryListListener\` \* \`MSAccountInfo\` \* \`MSAudioLocalClientEvent\` \* \`MSAudioLocalClientEvent\` \* \`MSAudioRecvPayload\` \* \`MSAudioRecvSignal\` \* \`MSAudioSendPayload\` \* \`MSAudioSendSignal\` \* \`MSConnectivity\` \* \`MSCredentialFilter\` \* \`MSCredentialParameters\` \* \`MSCredentials\` \* \`MSCredentialSpec\` \* \`MSDCCEvent\` \* \`MSDCCEventInit\` \* \`MSDelay\` \* \`MSDescription\` \* \`MSDSHEvent\` \* \`MSDSHEventInit\` \* \`MSFIDOCredentialParameters\` \* \`MSIceAddrType\` \* \`MSIceType\` \* \`MSIceWarningFlags\` \* \`MSInboundPayload\` \* \`MSIPAddressInfo\` \* \`MSJitter\` \* \`MSLocalClientEvent\` \* \`MSLocalClientEventBase\` \* \`MSNetwork\` \* \`MSNetworkConnectivityInfo\` \* \`MSNetworkInterfaceType\` \* \`MSOutboundNetwork\` \* \`MSOutboundPayload\` \* \`MSPacketLoss\` \* \`MSPayloadBase\` \* \`MSPortRange\` \* \`MSRelayAddress\` \* \`MSSignatureParameters\` \* \`MSStatsType\` \* \`MSStreamReader\` \* \`MSTransportDiagnosticsStats\` \* \`MSUtilization\` \* \`MSVideoPayload\` \* \`MSVideoRecvPayload\` \* \`MSVideoResolutionDistribution\` \* \`MSVideoSendPayload\` \* \`NotificationEventInit\` \* \`PushEventInit\` \* \`PushSubscriptionChangeInit\` \* \`RTCIdentityAssertionResult\` \* \`RTCIdentityProvider\` \* \`RTCIdentityProviderDetails\` \* \`RTCIdentityValidationResult\` \* \`Screen.deviceXDPI\` \* \`Screen.logicalXDPI\` \* \`SVGElement.xmlbase\` \* \`SVGGraphicsElement.farthestViewportElement\` \* \`SVGGraphicsElement.getTransformToElement\` \* \`SVGGraphicsElement.nearestViewportElement\` \* \`SVGStylable\` \* \`SVGTests.hasExtension\` \* \`SVGTests.requiredFeatures\` \* \`SyncEventInit\` \* \`ValidateAssertionCallback\` \* \`WebKitDirectoryEntry\` \* \`WebKitDirectoryReader\` \* \`WebKitEntriesCallback\` \* \`WebKitEntry\` \* \`WebKitErrorCallback\` \* \`WebKitFileCallback\` \* \`WebKitFileEntry\` \* \`WebKitFileSystem\` \* \`Window.clearImmediate\` \* \`Window.msSetImmediate\` \* \`Window.setImmediate\`
+- `CanvasRenderingContext2D.mozImageSmoothingEnabled`
+- `CanvasRenderingContext2D.msFillRule`
+- `CanvasRenderingContext2D.oImageSmoothingEnabled`
+- `CanvasRenderingContext2D.webkitImageSmoothingEnabled`
+- `Document.caretRangeFromPoint`
+- `Document.createExpression`
+- `Document.createNSResolver`
+- `Document.execCommandShowHelp`
+- `Document.exitFullscreen`
+- `Document.exitPointerLock`
+- `Document.focus`
+- `Document.fullscreenElement`
+- `Document.fullscreenEnabled`
+- `Document.getSelection`
+- `Document.msCapsLockWarningOff`
+- `Document.msCSSOMElementFloatMetrics`
+- `Document.msElementsFromRect`
+- `Document.msElementsFromPoint`
+- `Document.onvisibilitychange`
+- `Document.onwebkitfullscreenchange`
+- `Document.onwebkitfullscreenerror`
+- `Document.pointerLockElement`
+- `Document.queryCommandIndeterm`
+- `Document.URLUnencoded`
+- `Document.webkitCurrentFullScreenElement`
+- `Document.webkitFullscreenElement`
+- `Document.webkitFullscreenEnabled`
+- `Document.webkitIsFullScreen`
+- `Document.xmlEncoding`
+- `Document.xmlStandalone`
+- `Document.xmlVersion`
+- `DocumentType.entities`
+- `DocumentType.internalSubset`
+- `DocumentType.notations`
+- `DOML2DeprecatedSizeProperty`
+- `Element.msContentZoomFactor`
+- `Element.msGetUntransformedBounds`
+- `Element.msMatchesSelector`
+- `Element.msRegionOverflow`
+- `Element.msReleasePointerCapture`
+- `Element.msSetPointerCapture`
+- `Element.msZoomTo`
+- `Element.onwebkitfullscreenchange`
+- `Element.onwebkitfullscreenerror`
+- `Element.webkitRequestFullScreen`
+- `Element.webkitRequestFullscreen`
+- `ElementCSSInlineStyle`
+- `ExtendableEventInit`
+- `ExtendableMessageEventInit`
+- `FetchEventInit`
+- `GenerateAssertionCallback`
+- `HTMLAnchorElement.Methods`
+- `HTMLAnchorElement.mimeType`
+- `HTMLAnchorElement.nameProp`
+- `HTMLAnchorElement.protocolLong`
+- `HTMLAnchorElement.urn`
+- `HTMLAreasCollection`
+- `HTMLHeadElement.profile`
+- `HTMLImageElement.msGetAsCastingSource`
+- `HTMLImageElement.msGetAsCastingSource`
+- `HTMLImageElement.msKeySystem`
+- `HTMLImageElement.msPlayToDisabled`
+- `HTMLImageElement.msPlayToDisabled`
+- `HTMLImageElement.msPlayToPreferredSourceUri`
+- `HTMLImageElement.msPlayToPreferredSourceUri`
+- `HTMLImageElement.msPlayToPrimary`
+- `HTMLImageElement.msPlayToPrimary`
+- `HTMLImageElement.msPlayToSource`
+- `HTMLImageElement.msPlayToSource`
+- `HTMLImageElement.x`
+- `HTMLImageElement.y`
+- `HTMLInputElement.webkitdirectory`
+- `HTMLLinkElement.import`
+- `HTMLMetaElement.charset`
+- `HTMLMetaElement.url`
+- `HTMLSourceElement.msKeySystem`
+- `HTMLStyleElement.disabled`
+- `HTMLSummaryElement`
+- `MediaQueryListListener`
+- `MSAccountInfo`
+- `MSAudioLocalClientEvent`
+- `MSAudioLocalClientEvent`
+- `MSAudioRecvPayload`
+- `MSAudioRecvSignal`
+- `MSAudioSendPayload`
+- `MSAudioSendSignal`
+- `MSConnectivity`
+- `MSCredentialFilter`
+- `MSCredentialParameters`
+- `MSCredentials`
+- `MSCredentialSpec`
+- `MSDCCEvent`
+- `MSDCCEventInit`
+- `MSDelay`
+- `MSDescription`
+- `MSDSHEvent`
+- `MSDSHEventInit`
+- `MSFIDOCredentialParameters`
+- `MSIceAddrType`
+- `MSIceType`
+- `MSIceWarningFlags`
+- `MSInboundPayload`
+- `MSIPAddressInfo`
+- `MSJitter`
+- `MSLocalClientEvent`
+- `MSLocalClientEventBase`
+- `MSNetwork`
+- `MSNetworkConnectivityInfo`
+- `MSNetworkInterfaceType`
+- `MSOutboundNetwork`
+- `MSOutboundPayload`
+- `MSPacketLoss`
+- `MSPayloadBase`
+- `MSPortRange`
+- `MSRelayAddress`
+- `MSSignatureParameters`
+- `MSStatsType`
+- `MSStreamReader`
+- `MSTransportDiagnosticsStats`
+- `MSUtilization`
+- `MSVideoPayload`
+- `MSVideoRecvPayload`
+- `MSVideoResolutionDistribution`
+- `MSVideoSendPayload`
+- `NotificationEventInit`
+- `PushEventInit`
+- `PushSubscriptionChangeInit`
+- `RTCIdentityAssertionResult`
+- `RTCIdentityProvider`
+- `RTCIdentityProviderDetails`
+- `RTCIdentityValidationResult`
+- `Screen.deviceXDPI`
+- `Screen.logicalXDPI`
+- `SVGElement.xmlbase`
+- `SVGGraphicsElement.farthestViewportElement`
+- `SVGGraphicsElement.getTransformToElement`
+- `SVGGraphicsElement.nearestViewportElement`
+- `SVGStylable`
+- `SVGTests.hasExtension`
+- `SVGTests.requiredFeatures`
+- `SyncEventInit`
+- `ValidateAssertionCallback`
+- `WebKitDirectoryEntry`
+- `WebKitDirectoryReader`
+- `WebKitEntriesCallback`
+- `WebKitEntry`
+- `WebKitErrorCallback`
+- `WebKitFileCallback`
+- `WebKitFileEntry`
+- `WebKitFileSystem`
+- `Window.clearImmediate`
+- `Window.msSetImmediate`
+- `Window.setImmediate`
### 推荐:
-如果你的运行时能够保证这些名称是可用的(比如一个仅针对IE的应用),那么可以在本地添加那些声明,例如:
+如果你的运行时能够保证这些名称是可用的(比如一个仅针对 IE 的应用),那么可以在本地添加那些声明,例如:
对于`Element.msMatchesSelector`,在本地的`dom.ie.d.ts`文件里添加如下代码:
```typescript
interface Element {
- msMatchesSelector(selectors: string): boolean;
+ msMatchesSelector(selectors: string): boolean;
}
```
@@ -24,9 +176,9 @@ interface Element {
```typescript
interface Window {
- clearImmediate(handle: number): void;
- setImmediate(handler: (...args: any[]) => void): number;
- setImmediate(handler: any, ...args: any[]): number;
+ clearImmediate(handle: number): void;
+ setImmediate(handler: (...args: any[]) => void): number;
+ setImmediate(handler: any, ...args: any[]): number;
}
```
@@ -36,15 +188,14 @@ interface Window {
```typescript
function foo(x: T | (() => string)) {
- if (typeof x === "function") {
- x();
-// ~~~
-// Cannot invoke an expression whose type lacks a call signature. Type '(() => string) | (T & Function)' has no compatible call signatures.
- }
+ if (typeof x === 'function') {
+ x();
+ // ~~~
+ // Cannot invoke an expression whose type lacks a call signature. Type '(() => string) | (T & Function)' has no compatible call signatures.
+ }
}
```
这是因为,不同于以前的`T`会被细化掉,如今`T`会被扩展成`T & Function`。 然而,因为这个类型没有声明调用签名,类型系统无法找到通用的调用签名可以适用于`T & Function`和`() => string`。
因此,考虑使用一个更确切的类型,而不是`{}`或`Object`,并且考虑给`T`添加额外的约束条件。
-
diff --git a/zh/breaking-changes/typescript-3.2.md b/zh/breaking-changes/typescript-3.2.md
index de5f3d43..7829f8aa 100644
--- a/zh/breaking-changes/typescript-3.2.md
+++ b/zh/breaking-changes/typescript-3.2.md
@@ -14,5 +14,4 @@
## 参考
-* [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-32)
-
+- [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-32)
diff --git a/zh/breaking-changes/typescript-3.4.md b/zh/breaking-changes/typescript-3.4.md
index 95478071..7eed40e2 100644
--- a/zh/breaking-changes/typescript-3.4.md
+++ b/zh/breaking-changes/typescript-3.4.md
@@ -18,13 +18,20 @@ this.whargarbl = 10;
在某些情况下,TypeScript 3.4 的推断改进可能会产生泛型的函数,而不是那些接收并返回其约束的函数(通常是 `{}`)。
```typescript
-declare function compose(f: (arg: T) => U, g: (arg: U) => V): (arg: T) => V;
+declare function compose(
+ f: (arg: T) => U,
+ g: (arg: U) => V
+): (arg: T) => V;
-function list(x: T) { return [x]; }
-function box(value: T) { return { value }; }
+function list(x: T) {
+ return [x];
+}
+function box(value: T) {
+ return { value };
+}
let f = compose(list, box);
-let x = f(100)
+let x = f(100);
// 在 TypeScript 3.4 中, 'x.value' 的类型为
//
@@ -35,7 +42,7 @@ let x = f(100)
// {}[]
//
// 因此,插入一个 `string` 类型是错误的
-x.value.push("hello");
+x.value.push('hello');
```
`x` 上的显式类型注释可以清除这个错误。
@@ -46,11 +53,11 @@ TypeScript 现在使用函数调用时传入的类型(如下例中的 `then`
```typescript
function isEven(prom: Promise): Promise<{ success: boolean }> {
- return prom.then<{success: boolean}>((x) => {
- return x % 2 === 0 ?
- { success: true } :
- Promise.resolve({ success: false });
- });
+ return prom.then<{ success: boolean }>(x => {
+ return x % 2 === 0
+ ? { success: true }
+ : Promise.resolve({ success: false });
+ });
}
```
@@ -69,10 +76,10 @@ Argument of type '(x: number) => Promise<{ success: false; }> | { success: true;
```typescript
function isEven(prom: Promise): Promise<{ success: boolean }> {
// vvvvvvvvvvvvvvvvvv
- return prom.then<{success: boolean}>((x) => {
- return x % 2 === 0 ?
- { success: true } :
- Promise.resolve({ success: false });
+ return prom.then<{ success: boolean }>(x => {
+ return x % 2 === 0
+ ? { success: true }
+ : Promise.resolve({ success: false });
});
}
```
@@ -88,8 +95,12 @@ function isEven(prom: Promise): Promise<{ success: boolean }> {
这导致一个可见的重大变更,只要有类型参数的接口使用了 `keyof`(包括诸如 `Record` 之类的地方,这是涉及 `keyof K` 的类型别名)。下例就是这样一个可能的变更。
```typescript
-interface HasX { x: any }
-interface HasY { y: any }
+interface HasX {
+ x: any;
+}
+interface HasY {
+ y: any;
+}
declare const source: HasX | HasY;
declare const properties: KeyContainer;
@@ -99,7 +110,7 @@ interface KeyContainer {
}
function readKey(source: T, prop: KeyContainer) {
- console.log(source[prop.key])
+ console.log(source[prop.key]);
}
// 这个调用应该被拒绝,因为我们可能会这样做
@@ -111,5 +122,4 @@ readKey(source, properties);
## 参考
-* [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-34)
-
+- [原文](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#typescript-34)
diff --git a/zh/breaking-changes/typescript-3.5.md b/zh/breaking-changes/typescript-3.5.md
index f16c5e4c..e3052bd6 100644
--- a/zh/breaking-changes/typescript-3.5.md
+++ b/zh/breaking-changes/typescript-3.5.md
@@ -14,4 +14,3 @@ Duplicate identifier 'Omit'.
1. 删除重复定义的并使用 `lib.d.ts` 提供的。
2. 从模块中导出定义避免全局冲突。现有的用法可以使用 `import` 直接引用项目的旧 `Omit` 类型。
-
diff --git a/zh/breaking-changes/typescript-3.6.md b/zh/breaking-changes/typescript-3.6.md
index b9264b9b..c7e6dd9b 100644
--- a/zh/breaking-changes/typescript-3.6.md
+++ b/zh/breaking-changes/typescript-3.6.md
@@ -6,8 +6,8 @@
```typescript
class C {
- "constructor"() {
- console.log("现在我是构造函数了。");
+ constructor() {
+ console.log('现在我是构造函数了。');
}
}
```
@@ -16,8 +16,8 @@ class C {
```typescript
class D {
- ["constructor"]() {
- console.log("我只是一个纯粹的方法,不是构造函数!")
+ ['constructor']() {
+ console.log('我只是一个纯粹的方法,不是构造函数!');
}
}
```
@@ -26,10 +26,10 @@ class D {
`lib.dom.d.ts` 中移除或者修改了大量的定义。其中包括(但不仅限于)以下这些:
-* 全局的 `window` 不再定义为 `Window`,它被更明确的定义 `type Window & typeof globalThis` 替代。在某些情况下,将它作为 `typeof window` 更好。
-* `GlobalFetch` 已经被移除。使用 `WindowOrWorkerGlobalScrope` 替代。
-* `Navigator` 上明确的非标准的属性已经被移除了。
-* `experimental-webgl` 上下文已经被移除了。使用 `webgl` 或 `webgl2` 替代。
+- 全局的 `window` 不再定义为 `Window`,它被更明确的定义 `type Window & typeof globalThis` 替代。在某些情况下,将它作为 `typeof window` 更好。
+- `GlobalFetch` 已经被移除。使用 `WindowOrWorkerGlobalScrope` 替代。
+- `Navigator` 上明确的非标准的属性已经被移除了。
+- `experimental-webgl` 上下文已经被移除了。使用 `webgl` 或 `webgl2` 替代。
如果你认为其中的改变已经制造了错误,[请提交一个 issue](https://github.com/Microsoft/TSJS-lib-generator/)。
@@ -63,5 +63,4 @@ while (true) {
## 参考
-* [Announcing TypeScript 3.6](https://devblogs.microsoft.com/typescript/announcing-typescript-3-6/#breaking-changes)
-
+- [Announcing TypeScript 3.6](https://devblogs.microsoft.com/typescript/announcing-typescript-3-6/#breaking-changes)
diff --git a/zh/declaration-files/README.md b/zh/declaration-files/README.md
index 0363ec10..e617194b 100644
--- a/zh/declaration-files/README.md
+++ b/zh/declaration-files/README.md
@@ -1,9 +1,9 @@
-- [如何书写声明文件](./README.md)
- - [介绍](./introduction.md)
- - [举例](./by-example.md)
- - [库结构](./library-structures.md)
- - [模板](./templates.md)
- - [最佳实践](./do-s-and-don-ts.md)
- - [深入](./deep-dive.md)
- - [发布](./publishing.md)
- - [使用](./consumption.md)
+- [如何书写声明文件](./README.md)
+ - [介绍](./introduction.md)
+ - [举例](./by-example.md)
+ - [库结构](./library-structures.md)
+ - [模板](./templates.md)
+ - [最佳实践](./do-s-and-don-ts.md)
+ - [深入](./deep-dive.md)
+ - [发布](./publishing.md)
+ - [使用](./consumption.md)
diff --git a/zh/declaration-files/by-example.md b/zh/declaration-files/by-example.md
index 9490c3a9..c71aa989 100644
--- a/zh/declaration-files/by-example.md
+++ b/zh/declaration-files/by-example.md
@@ -6,14 +6,14 @@
这些例子是按复杂度递增的顺序组织的。
-- [带属性的对象](#带属性的对象)
-- [函数重载](#函数重载)
-- [可重用类型(接口)](#可重用类型接口)
-- [可重用类型(类型别名)](#可重用类型类型别名)
-- [组织类型](#组织类型)
-- [类](#类)
-- [全局变量](#全局变量)
-- [全局函数](#全局函数)
+- [带属性的对象](#带属性的对象)
+- [函数重载](#函数重载)
+- [可重用类型(接口)](#可重用类型接口)
+- [可重用类型(类型别名)](#可重用类型类型别名)
+- [组织类型](#组织类型)
+- [类](#类)
+- [全局变量](#全局变量)
+- [全局函数](#全局函数)
## 带属性的对象
@@ -37,8 +37,8 @@ _声明_
```ts
declare namespace myLib {
- function makeGreeting(s: string): string;
- let numberOfGreetings: number;
+ function makeGreeting(s: string): string;
+ let numberOfGreetings: number;
}
```
@@ -80,8 +80,8 @@ _代码_
```ts
greet({
- greeting: 'hello world',
- duration: 4000,
+ greeting: 'hello world',
+ duration: 4000,
});
```
@@ -91,9 +91,9 @@ _声明_
```ts
interface GreetingSettings {
- greeting: string;
- duration?: number;
- color?: string;
+ greeting: string;
+ duration?: number;
+ color?: string;
}
declare function greet(setting: GreetingSettings): void;
@@ -109,7 +109,7 @@ _代码_
```ts
function getGreeting() {
- return 'howdy';
+ return 'howdy';
}
class MyGreeter extends Greeter {}
@@ -149,14 +149,14 @@ _声明_
```ts
declare namespace GreetingLib {
- interface LogOptions {
- verbose?: boolean;
- }
- interface AlertOptions {
- modal: boolean;
- title?: string;
- color?: string;
- }
+ interface LogOptions {
+ verbose?: boolean;
+ }
+ interface AlertOptions {
+ modal: boolean;
+ title?: string;
+ color?: string;
+ }
}
```
@@ -164,15 +164,15 @@ declare namespace GreetingLib {
```ts
declare namespace GreetingLib.Options {
- // Refer to via GreetingLib.Options.Log
- interface Log {
- verbose?: boolean;
- }
- interface Alert {
- modal: boolean;
- title?: string;
- color?: string;
- }
+ // Refer to via GreetingLib.Options.Log
+ interface Log {
+ verbose?: boolean;
+ }
+ interface Alert {
+ modal: boolean;
+ title?: string;
+ color?: string;
+ }
}
```
@@ -190,9 +190,9 @@ myGreeter.greeting = 'howdy';
myGreeter.showGreeting();
class SpecialGreeter extends Greeter {
- constructor() {
- super('Very special greetings');
- }
+ constructor() {
+ super('Very special greetings');
+ }
}
```
@@ -203,10 +203,10 @@ _声明_
```ts
declare class Greeter {
- constructor(greeting: string);
+ constructor(greeting: string);
- greeting: string;
- showGreeting(): void;
+ greeting: string;
+ showGreeting(): void;
}
```
diff --git a/zh/declaration-files/deep-dive.md b/zh/declaration-files/deep-dive.md
index a77cdad2..ba310095 100644
--- a/zh/declaration-files/deep-dive.md
+++ b/zh/declaration-files/deep-dive.md
@@ -4,7 +4,7 @@
比如,你可能想要这样一个模块,可以用或不用`new`来创建不同的类型,在不同层级上暴露出不同的命名类型,且模块对象上还带有一些属性。
阅读这篇指南后,你就会了解如何编写复杂的声明文件来提供友好的 API 。
-这篇指南针对于模块(或UMD)代码库,因为它们的选择具有更高的可变性。
+这篇指南针对于模块(或 UMD)代码库,因为它们的选择具有更高的可变性。
## 核心概念
@@ -14,11 +14,11 @@
如果你正在阅读这篇指南,你可能已经大概了解 TypeScript 里的类型指是什么。 明确一下,*类型*通过以下方式引入:
-- 类型别名声明(`type sn = number | string;`)
-- 接口声明(`interface I { x: number[]; }`)
-- 类声明(`class C { }`)
-- 枚举声明(`enum E { A, B, C }`)
-- 指向某个类型的`import`声明
+- 类型别名声明(`type sn = number | string;`)
+- 接口声明(`interface I { x: number[]; }`)
+- 类声明(`class C { }`)
+- 枚举声明(`enum E { A, B, C }`)
+- 指向某个类型的`import`声明
以上每种声明形式都会创建一个新的类型名称。
@@ -30,12 +30,12 @@
同样地,以下方式能够创建值:
-- `let`,`const`,和`var`声明
-- 包含值的`namespace`或`module`声明
-- `enum`声明
-- `class`声明
-- 指向值的`import`声明
-- `function`声明
+- `let`,`const`,和`var`声明
+- 包含值的`namespace`或`module`声明
+- `enum`声明
+- `class`声明
+- 指向值的`import`声明
+- `function`声明
### 命名空间
@@ -72,7 +72,7 @@ export interface SomeType {
这样使用它:
```ts
-import * as foo from "./foo";
+import * as foo from './foo';
let x: foo.SomeType = foo.SomeVar.a;
console.log(x.count);
```
@@ -90,7 +90,7 @@ export interface Bar {
这提供了使用解构的机会:
```ts
-import { Bar } from "./foo";
+import { Bar } from './foo';
let x: Bar = Bar.a;
console.log(x.count);
```
@@ -192,20 +192,20 @@ type X = string;
在这个例子里,第一个代码块创建了以下名字与含义:
-- 一个值`X`(因为`namespace`声明包含一个值,`Z`)
-- 一个命名空间`X`(因为`namespace`声明包含一个类型,`Y`)
-- 在命名空间`X`里的类型`Y`
-- 在命名空间`X`里的类型`Z`(类的实例结构)
-- 值`X`的一个属性值`Z`(类的构造函数)
+- 一个值`X`(因为`namespace`声明包含一个值,`Z`)
+- 一个命名空间`X`(因为`namespace`声明包含一个类型,`Y`)
+- 在命名空间`X`里的类型`Y`
+- 在命名空间`X`里的类型`Z`(类的实例结构)
+- 值`X`的一个属性值`Z`(类的构造函数)
第二个代码块创建了以下名字与含义:
-- 值`Y`(`number`类型),它是值`X`的一个属性
-- 一个命名空间`Z`
-- 值`Z`,它是值`X`的一个属性
-- 在`X.Z`命名空间下的类型`C`
-- 值`X.Z`的一个属性值`C`
-- 类型`X`
+- 值`Y`(`number`类型),它是值`X`的一个属性
+- 一个命名空间`Z`
+- 值`Z`,它是值`X`的一个属性
+- 在`X.Z`命名空间下的类型`C`
+- 值`X.Z`的一个属性值`C`
+- 类型`X`
## 使用`export =`或`import`
diff --git a/zh/declaration-files/do-s-and-don-ts.md b/zh/declaration-files/do-s-and-don-ts.md
index a64c9b10..5d57a510 100644
--- a/zh/declaration-files/do-s-and-don-ts.md
+++ b/zh/declaration-files/do-s-and-don-ts.md
@@ -44,7 +44,7 @@ function reverse(s: string): string;
```ts
/* 错误 */
function fn(x: () => any) {
- x();
+ x();
}
```
@@ -53,7 +53,7 @@ function fn(x: () => any) {
```ts
/* 正确 */
function fn(x: () => void) {
- x();
+ x();
}
```
@@ -61,8 +61,8 @@ _原因_:使用`void`相对安全,因为它能防止不小心使用了未经
```ts
function fn(x: () => void) {
- var k = x(); // oops! meant to do something else
- k.doSomething(); // error, but would be OK if the return type had been 'any'
+ var k = x(); // oops! meant to do something else
+ k.doSomething(); // error, but would be OK if the return type had been 'any'
}
```
@@ -73,7 +73,7 @@ function fn(x: () => void) {
```ts
/* 错误 */
interface Fetcher {
- getObject(done: (data: any, elapsedTime?: number) => void): void;
+ getObject(done: (data: any, elapsedTime?: number) => void): void;
}
```
@@ -86,7 +86,7 @@ interface Fetcher {
```ts
/* 正确 */
interface Fetcher {
- getObject(done: (data: any, elapsedTime: number) => void): void;
+ getObject(done: (data: any, elapsedTime: number) => void): void;
}
```
@@ -98,8 +98,8 @@ interface Fetcher {
/* WRONG */
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(
- action: (done: DoneFn) => void,
- timeout?: number
+ action: (done: DoneFn) => void,
+ timeout?: number
): void;
```
@@ -108,8 +108,8 @@ declare function beforeAll(
```ts
/* 正确 */
declare function beforeAll(
- action: (done: DoneFn) => void,
- timeout?: number
+ action: (done: DoneFn) => void,
+ timeout?: number
): void;
```
@@ -154,9 +154,9 @@ _原因_:当解析函数调用的时候,TypeScript 会选择*匹配到的第
```ts
/* WRONG */
interface Example {
- diff(one: string): number;
- diff(one: string, two: string): number;
- diff(one: string, two: string, three: boolean): number;
+ diff(one: string): number;
+ diff(one: string, two: string): number;
+ diff(one: string, two: string, three: boolean): number;
}
```
@@ -165,7 +165,7 @@ interface Example {
```ts
/* OK */
interface Example {
- diff(one: string, two?: string, three?: boolean): number;
+ diff(one: string, two?: string, three?: boolean): number;
}
```
@@ -193,7 +193,7 @@ fn(x.diff);
var x: Example;
// When written with overloads, incorrectly an error because of passing 'undefined' to 'string'
// When written with optionals, correctly OK
-x.diff("something", true ? undefined : "hour");
+x.diff('something', true ? undefined : 'hour');
```
### 使用联合类型
diff --git a/zh/declaration-files/introduction.md b/zh/declaration-files/introduction.md
index f4ea442f..b7deaa21 100644
--- a/zh/declaration-files/introduction.md
+++ b/zh/declaration-files/introduction.md
@@ -25,13 +25,13 @@
在[模版](./templates.md)一节里,你能找到一些声明文件,它们对于编写新的声明文件来讲会有所帮助。
如果你已经了解了库的结构,那么可以阅读相应的模版文件:
-- [global-modifying-module.d.ts](templates/global-modifying-module.d.ts.md)
-- [global-plugin.d.ts](templates/global-plugin.d.ts.md)
-- [global.d.ts](templates/global.d.ts.md)
-- [module-class.d.ts](templates/module-class.d.ts.md)
-- [module-function.d.ts](templates/module-function.d.ts.md)
-- [module-plugin.d.ts](templates/module-plugin.d.ts.md)
-- [module.d.ts](templates/module.d.ts.md)
+- [global-modifying-module.d.ts](templates/global-modifying-module.d.ts.md)
+- [global-plugin.d.ts](templates/global-plugin.d.ts.md)
+- [global.d.ts](templates/global.d.ts.md)
+- [module-class.d.ts](templates/module-class.d.ts.md)
+- [module-function.d.ts](templates/module-function.d.ts.md)
+- [module-plugin.d.ts](templates/module-plugin.d.ts.md)
+- [module.d.ts](templates/module.d.ts.md)
## [规范](./do-s-and-don-ts.md)
diff --git a/zh/declaration-files/library-structures.md b/zh/declaration-files/library-structures.md
index ba96e46f..066c2691 100644
--- a/zh/declaration-files/library-structures.md
+++ b/zh/declaration-files/library-structures.md
@@ -23,11 +23,11 @@
1. 如何获取代码库?
- 比如,是否只能够从 npm 或 CDN 获取。
+ 比如,是否只能够从 npm 或 CDN 获取。
2. 如何导入代码库?
- 它是否添加了某个全局对象?它是否使用了`require`或`import`/`export`语句?
+ 它是否添加了某个全局对象?它是否使用了`require`或`import`/`export`语句?
## 针对不同类型的代码库的示例
@@ -70,22 +70,22 @@ define(..., ['someLib'], function(someLib) {
模块化代码库至少会包含以下代表性条目之一:
-- 无条件的调用`require`或`define`
-- 像`import * as a from 'b';`或`export c;`这样的声明
-- 赋值给`exports`或`module.exports`
+- 无条件的调用`require`或`define`
+- 像`import * as a from 'b';`或`export c;`这样的声明
+- 赋值给`exports`或`module.exports`
它们极少包含:
-- 对`window`或`global`的赋值
+- 对`window`或`global`的赋值
#### 模块化代码库的模版
有以下四个模版可用:
-- [`module.d.ts`](./templates/module.d.ts.md)
-- [`module-class.d.ts`](./templates/module-class.d.ts.md)
-- [`module-function.d.ts`](./templates/module-function.d.ts.md)
-- [`module-plugin.d.ts`](./templates/module-plugin.d.ts.md)
+- [`module.d.ts`](./templates/module.d.ts.md)
+- [`module-class.d.ts`](./templates/module-class.d.ts.md)
+- [`module-function.d.ts`](./templates/module-function.d.ts.md)
+- [`module-plugin.d.ts`](./templates/module-plugin.d.ts.md)
你应该先阅读[`module.d.ts`](./templates/module.d.ts.md)以便从整体上了解它们的工作方式。
@@ -120,7 +120,7 @@ require('jest-matchers-files');
```ts
$(() => {
- console.log('hello!');
+ console.log('hello!');
});
```
@@ -141,7 +141,7 @@ UMD 代码库与全局代码库很难通过文档来识别。
```js
function createGreeting(s) {
- return 'Hello, ' + s;
+ return 'Hello, ' + s;
}
```
@@ -149,22 +149,22 @@ function createGreeting(s) {
```js
window.createGreeting = function (s) {
- return 'Hello, ' + s;
+ return 'Hello, ' + s;
};
```
在阅读全局代码库的代码时,你会看到:
-- 顶层的`var`语句或`function`声明
-- 一个或多个`window.someName`赋值语句
-- 假设 DOM 相关的原始值`document`或`window`存在
+- 顶层的`var`语句或`function`声明
+- 一个或多个`window.someName`赋值语句
+- 假设 DOM 相关的原始值`document`或`window`存在
你不会看到:
-- 检查或使用了模块加载器,如`require`或`define`
-- CommonJS/Node.js 风格的导入语句,如`var fs = require("fs");`
-- `define(...)`调用
-- 描述`require`或导入代码库的文档
+- 检查或使用了模块加载器,如`require`或`define`
+- CommonJS/Node.js 风格的导入语句,如`var fs = require("fs");`
+- `define(...)`调用
+- 描述`require`或导入代码库的文档
#### 全局代码库的示例
@@ -337,7 +337,7 @@ import * as someLib from 'someLib';
```ts
declare namespace cats {
- interface KittySettings {}
+ interface KittySettings {}
}
```
diff --git a/zh/declaration-files/publishing.md b/zh/declaration-files/publishing.md
index 5a5ade33..eb2a7690 100644
--- a/zh/declaration-files/publishing.md
+++ b/zh/declaration-files/publishing.md
@@ -18,11 +18,11 @@ TypeScript 工程和 JavaScript 工程都可以使用[`--declaration`](/tsconfig
```json
{
- "name": "awesome",
- "author": "Vandelay Industries",
- "version": "1.0.0",
- "main": "./lib/main.js",
- "types": "./lib/main.d.ts"
+ "name": "awesome",
+ "author": "Vandelay Industries",
+ "version": "1.0.0",
+ "main": "./lib/main.js",
+ "types": "./lib/main.d.ts"
}
```
@@ -38,16 +38,16 @@ TypeScript 工程和 JavaScript 工程都可以使用[`--declaration`](/tsconfig
```json
{
- "name": "browserify-typescript-extension",
- "author": "Vandelay Industries",
- "version": "1.0.0",
- "main": "./lib/main.js",
- "types": "./lib/main.d.ts",
- "dependencies": {
- "browserify": "latest",
- "@types/browserify": "latest",
- "typescript": "next"
- }
+ "name": "browserify-typescript-extension",
+ "author": "Vandelay Industries",
+ "version": "1.0.0",
+ "main": "./lib/main.js",
+ "types": "./lib/main.d.ts",
+ "dependencies": {
+ "browserify": "latest",
+ "@types/browserify": "latest",
+ "typescript": "next"
+ }
}
```
@@ -80,9 +80,9 @@ TypeScript 工程和 JavaScript 工程都可以使用[`--declaration`](/tsconfig
如果你的类型声明依赖于另一个包:
-- *不要*把依赖的包放进你的包里,保持它们在各自的文件里。
-- *不要*将声明拷贝到你的包里。
-- *应该*依赖在 npm 上的类型声明包,如果依赖包没包含它自己的声明文件的话。
+- *不要*把依赖的包放进你的包里,保持它们在各自的文件里。
+- *不要*将声明拷贝到你的包里。
+- *应该*依赖在 npm 上的类型声明包,如果依赖包没包含它自己的声明文件的话。
## 使用`typesVersions`选择版本
@@ -92,12 +92,12 @@ TypeScript 工程和 JavaScript 工程都可以使用[`--declaration`](/tsconfig
```json
{
- "name": "package-name",
- "version": "1.0",
- "types": "./index.d.ts",
- "typesVersions": {
- ">=3.1": { "*": ["ts3.1/*"] }
- }
+ "name": "package-name",
+ "version": "1.0",
+ "types": "./index.d.ts",
+ "typesVersions": {
+ ">=3.1": { "*": ["ts3.1/*"] }
+ }
}
```
@@ -121,13 +121,13 @@ TypeScript 是根据 Node.js 的[语言化版本](https://github.com/npm/node-se
```json tsconfig
{
- "name": "package-name",
- "version": "1.0",
- "types": "./index.d.ts",
- "typesVersions": {
- ">=3.2": { "*": ["ts3.2/*"] },
- ">=3.1": { "*": ["ts3.1/*"] }
- }
+ "name": "package-name",
+ "version": "1.0",
+ "types": "./index.d.ts",
+ "typesVersions": {
+ ">=3.2": { "*": ["ts3.2/*"] },
+ ">=3.1": { "*": ["ts3.1/*"] }
+ }
}
```
@@ -136,14 +136,14 @@ TypeScript 是根据 Node.js 的[语言化版本](https://github.com/npm/node-se
```jsonc tsconfig
{
- "name": "package-name",
- "version": "1.0",
- "types": "./index.d.ts",
- "typesVersions": {
- // NOTE: this doesn't work!
- ">=3.1": { "*": ["ts3.1/*"] },
- ">=3.2": { "*": ["ts3.2/*"] }
- }
+ "name": "package-name",
+ "version": "1.0",
+ "types": "./index.d.ts",
+ "typesVersions": {
+ // NOTE: this doesn't work!
+ ">=3.1": { "*": ["ts3.1/*"] },
+ ">=3.2": { "*": ["ts3.2/*"] }
+ }
}
```
diff --git a/zh/declaration-files/templates.md b/zh/declaration-files/templates.md
index f25676f6..2bd1a591 100644
--- a/zh/declaration-files/templates.md
+++ b/zh/declaration-files/templates.md
@@ -1,10 +1,9 @@
# 模板
-* [global-modifying-module.d.ts](templates/global-modifying-module.d.ts.md)
-* [global-plugin.d.ts](templates/global-plugin.d.ts.md)
-* [global.d.ts](templates/global.d.ts.md)
-* [module-class.d.ts](templates/module-class.d.ts.md)
-* [module-function.d.ts](templates/module-function.d.ts.md)
-* [module-plugin.d.ts](templates/module-plugin.d.ts.md)
-* [module.d.ts](templates/module.d.ts.md)
-
+- [global-modifying-module.d.ts](templates/global-modifying-module.d.ts.md)
+- [global-plugin.d.ts](templates/global-plugin.d.ts.md)
+- [global.d.ts](templates/global.d.ts.md)
+- [module-class.d.ts](templates/module-class.d.ts.md)
+- [module-function.d.ts](templates/module-function.d.ts.md)
+- [module-plugin.d.ts](templates/module-plugin.d.ts.md)
+- [module.d.ts](templates/module.d.ts.md)
diff --git a/zh/declaration-files/templates/global-plugin.d.ts.md b/zh/declaration-files/templates/global-plugin.d.ts.md
index 5ca0ad47..96cd2cbd 100644
--- a/zh/declaration-files/templates/global-plugin.d.ts.md
+++ b/zh/declaration-files/templates/global-plugin.d.ts.md
@@ -47,9 +47,9 @@ console.log(moment.format());
针对模块,共存在三个模版。它们是:
-- [`module.d.ts`](./templates/module.d.ts.md)
-- [`module-class.d.ts`](./templates/module-class.d.ts.md)
-- [`module-function.d.ts`](./templates/module-function.d.ts.md)
+- [`module.d.ts`](./templates/module.d.ts.md)
+- [`module-class.d.ts`](./templates/module-class.d.ts.md)
+- [`module-function.d.ts`](./templates/module-function.d.ts.md)
若一个模块可以当作函数调用,则使用[`module-function.d.ts`](./templates/module-function.d.ts.md)。
@@ -203,7 +203,7 @@ import * as someLib from 'someLib';
```ts
declare namespace cats {
- interface KittySettings {}
+ interface KittySettings {}
}
```
@@ -243,7 +243,7 @@ var app = exp();
一个代码库可以包含多个模块,比如:
-```
+```txt
myLib
+---- index.js
+---- foo.js
@@ -263,7 +263,7 @@ var d = require('myLib/bar/baz');
声明文件如下:
-```
+```txt
@types/myLib
+---- index.d.ts
+---- foo.d.ts
@@ -284,22 +284,22 @@ var d = require('myLib/bar/baz');
*~ the built-in number type.
*/
interface Number {
- toBinaryString(opts?: MyLibrary.BinaryFormatOptions): string;
+ toBinaryString(opts?: MyLibrary.BinaryFormatOptions): string;
- toBinaryString(
- callback: MyLibrary.BinaryFormatCallback,
- opts?: MyLibrary.BinaryFormatOptions
- ): string;
+ toBinaryString(
+ callback: MyLibrary.BinaryFormatCallback,
+ opts?: MyLibrary.BinaryFormatOptions
+ ): string;
}
/*~ If you need to declare several types, place them inside a namespace
*~ to avoid adding too many things to the global namespace.
*/
declare namespace MyLibrary {
- type BinaryFormatCallback = (n: number) => string;
- interface BinaryFormatOptions {
- prefix?: string;
- padding: number;
- }
+ type BinaryFormatCallback = (n: number) => string;
+ interface BinaryFormatOptions {
+ prefix?: string;
+ padding: number;
+ }
}
```
diff --git a/zh/declaration-files/templates/global.d.ts.md b/zh/declaration-files/templates/global.d.ts.md
index f82dfe2d..268e5a91 100644
--- a/zh/declaration-files/templates/global.d.ts.md
+++ b/zh/declaration-files/templates/global.d.ts.md
@@ -6,7 +6,7 @@
```ts
$(() => {
- console.log('hello!');
+ console.log('hello!');
});
```
@@ -27,7 +27,7 @@ UMD 代码库与全局代码库很难通过文档来识别。
```js
function createGreeting(s) {
- return 'Hello, ' + s;
+ return 'Hello, ' + s;
}
```
@@ -35,22 +35,22 @@ function createGreeting(s) {
```js
window.createGreeting = function (s) {
- return 'Hello, ' + s;
+ return 'Hello, ' + s;
};
```
在阅读全局代码库的代码时,你会看到:
-- 顶层的`var`语句或`function`声明
-- 一个或多个`window.someName`赋值语句
-- 假设 DOM 相关的原始值`document`或`window`存在
+- 顶层的`var`语句或`function`声明
+- 一个或多个`window.someName`赋值语句
+- 假设 DOM 相关的原始值`document`或`window`存在
你不会看到:
-- 检查或使用了模块加载器,如`require`或`define`
-- CommonJS/Node.js 风格的导入语句,如`var fs = require("fs");`
-- `define(...)`调用
-- 描述`require`或导入代码库的文档
+- 检查或使用了模块加载器,如`require`或`define`
+- CommonJS/Node.js 风格的导入语句,如`var fs = require("fs");`
+- `define(...)`调用
+- 描述`require`或导入代码库的文档
## 全局代码库的示例
@@ -81,9 +81,9 @@ declare function myLib(a: number): number;
*~ delete this declaration and add types inside the namespace below.
*/
interface myLib {
- name: string;
- length: number;
- extras?: string[];
+ name: string;
+ length: number;
+ extras?: string[];
}
/*~ If your library has properties exposed on a global variable,
@@ -91,37 +91,37 @@ interface myLib {
*~ You should also place types (interfaces and type alias) here.
*/
declare namespace myLib {
- //~ We can write 'myLib.timeout = 50;'
- let timeout: number;
-
- //~ We can access 'myLib.version', but not change it
- const version: string;
-
- //~ There's some class we can create via 'let c = new myLib.Cat(42)'
- //~ Or reference e.g. 'function f(c: myLib.Cat) { ... }
- class Cat {
- constructor(n: number);
-
- //~ We can read 'c.age' from a 'Cat' instance
- readonly age: number;
-
- //~ We can invoke 'c.purr()' from a 'Cat' instance
- purr(): void;
- }
-
- //~ We can declare a variable as
- //~ 'var s: myLib.CatSettings = { weight: 5, name: "Maru" };'
- interface CatSettings {
- weight: number;
- name: string;
- tailLength?: number;
- }
-
- //~ We can write 'const v: myLib.VetID = 42;'
- //~ or 'const v: myLib.VetID = "bob";'
- type VetID = string | number;
-
- //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);'
- function checkCat(c: Cat, s?: VetID);
+ //~ We can write 'myLib.timeout = 50;'
+ let timeout: number;
+
+ //~ We can access 'myLib.version', but not change it
+ const version: string;
+
+ //~ There's some class we can create via 'let c = new myLib.Cat(42)'
+ //~ Or reference e.g. 'function f(c: myLib.Cat) { ... }
+ class Cat {
+ constructor(n: number);
+
+ //~ We can read 'c.age' from a 'Cat' instance
+ readonly age: number;
+
+ //~ We can invoke 'c.purr()' from a 'Cat' instance
+ purr(): void;
+ }
+
+ //~ We can declare a variable as
+ //~ 'var s: myLib.CatSettings = { weight: 5, name: "Maru" };'
+ interface CatSettings {
+ weight: number;
+ name: string;
+ tailLength?: number;
+ }
+
+ //~ We can write 'const v: myLib.VetID = 42;'
+ //~ or 'const v: myLib.VetID = "bob";'
+ type VetID = string | number;
+
+ //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);'
+ function checkCat(c: Cat, s?: VetID);
}
```
diff --git a/zh/handbook-v2/basics.md b/zh/handbook-v2/basics.md
index 5fa852e0..e877238b 100644
--- a/zh/handbook-v2/basics.md
+++ b/zh/handbook-v2/basics.md
@@ -26,7 +26,7 @@ message();
假设 `message` 是这样定义的:
```js
-const message = "Hello World!";
+const message = 'Hello World!';
```
你可能很容易猜到,如果执行 `message.toLowerCase()`,我们将会得到一个所有字母都是小写的字符串。
@@ -65,7 +65,7 @@ function fn(x) {
```ts twoslash
// @errors: 2349
-const message = "hello!";
+const message = 'hello!';
message();
```
@@ -80,8 +80,8 @@ message();
```js
const user = {
- name: 'Daniel',
- age: 26,
+ name: 'Daniel',
+ age: 26,
};
user.location; // 返回 undefined
```
@@ -91,7 +91,7 @@ user.location; // 返回 undefined
```ts twoslash
// @errors: 2339
const user = {
- name: "Daniel",
+ name: 'Daniel',
age: 26,
};
@@ -104,12 +104,12 @@ user.location;
```ts twoslash
// @noErrors
-const announcement = "Hello World!";
-
+const announcement = 'Hello World!';
+
// 你需要花多久才能注意到拼写错误?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();
-
+
// 实际上正确的拼写是这样的……
announcement.toLocaleLowerCase();
```
@@ -129,11 +129,11 @@ function flipCoin() {
```ts twoslash
// @errors: 2367
-const value = Math.random() < 0.5 ? "a" : "b";
-if (value !== "a") {
+const value = Math.random() < 0.5 ? 'a' : 'b';
+if (value !== 'a') {
// ...
-} else if (value === "b") {
-// 永远无法到达这个分支
+} else if (value === 'b') {
+ // 永远无法到达这个分支
}
```
@@ -145,17 +145,15 @@ TypeScript 可以在我们的代码出现错误时捕获 bug。这很好,但
这意味着 TypeScript 也能用于编辑代码。我们在编辑器中输入的时候,核心的类型检查器能够提供报错信息和代码补全。人们经常会谈到 TypeScript 在工具层面的作用,这就是一个典型的例子。
-
-
-```ts twoslash
+```ts
// @noErrors
// @esModuleInterop
-import express from "express";
+import express from 'express';
const app = express();
-app.get("/", function (req, res) {
+app.get('/', function (req, res) {
res.sen
-// ^|
+ // ^|
});
app.listen(3000);
@@ -207,7 +205,7 @@ function greet(person, date) {
console.log(`Hello ${person}, today is ${date}!`);
}
-greet("Brendan");
+greet('Brendan');
```
如果我们再次执行 `tsc hello.ts`,那么会注意到命令行抛出了错误!
@@ -252,7 +250,7 @@ function greet(person: string, date: Date) {
console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
-greet("Maddison", Date());
+greet('Maddison', Date());
```
什么?TypeScript 报错提示第二个参数有问题,但这是为什么呢?你可能会有点惊讶,因为在 JavaScript 中直接调用 `Date()` 返回的是 `string`。另一方面,通过 `new Date()` 去构造 `Date`,则可以如预期那样返回 `Date` 对象。
@@ -263,14 +261,14 @@ greet("Maddison", Date());
function greet(person: string, date: Date) {
console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
-
-greet("Maddison", new Date());
+
+greet('Maddison', new Date());
```
记住,我们并不总是需要显式地进行类型注解。在很多情况下,即使省略了类型注解,TypeScript 也可以为我们*推断出*(或者“搞清楚”)类型。
```ts twoslash
-let msg = "hello there!";
+let msg = 'hello there!';
// ^?
```
@@ -289,7 +287,7 @@ function greet(person: string, date: Date) {
console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
-greet("Maddison", new Date());
+greet('Maddison', new Date());
```
注意到有两个变化:
@@ -312,7 +310,7 @@ greet("Maddison", new Date());
被重写为:
```js
-"Hello " + person + ", today is " + date.toDateString() + "!";
+'Hello ' + person + ', today is ' + date.toDateString() + '!';
```
为什么会这样子呢?
@@ -325,7 +323,7 @@ greet("Maddison", new Date());
function greet(person, date) {
console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
-greet("Maddison", new Date());
+greet('Maddison', new Date());
```
> 虽然默认的目标代码采用的是 ES3 语法,但现在浏览器大多数都已经支持 ES2015 了。 >
diff --git a/zh/handbook-v2/classes.md b/zh/handbook-v2/classes.md
index 68879c23..24f88136 100644
--- a/zh/handbook-v2/classes.md
+++ b/zh/handbook-v2/classes.md
@@ -36,7 +36,7 @@ pt.y = 0;
与其他位置一样,类型注解是可选的,但如果未指定,则会隐式为 `any` 类型。
-字段还可以有_初始化器_;当类被实例化时,它们将自动运行:
+字段还可以有*初始化器*;当类被实例化时,它们将自动运行:
```ts twoslash
class Point {
@@ -59,7 +59,7 @@ class Point {
}
// ---cut---
const pt = new Point();
-pt.x = "0";
+pt.x = '0';
```
#### `--strictPropertyInitialization`
@@ -78,14 +78,14 @@ class GoodGreeter {
name: string;
constructor() {
- this.name = "hello";
+ this.name = 'hello';
}
}
```
-请注意,字段需要在_构造函数内部_进行初始化。TypeScript 在检测初始化时不会分析从构造函数中调用的方法,因为派生类可能会覆写这些方法,并未初始化成员。
+请注意,字段需要在*构造函数内部*进行初始化。TypeScript 在检测初始化时不会分析从构造函数中调用的方法,因为派生类可能会覆写这些方法,并未初始化成员。
-如果你打算通过构造函数以外的方式明确初始化字段(例如,也许外部库填充类的一部分内容),你可以使用_明确赋值断言操作符_ `!`:
+如果你打算通过构造函数以外的方式明确初始化字段(例如,也许外部库填充类的一部分内容),你可以使用*明确赋值断言操作符* `!`:
```ts twoslash
class OKGreeter {
@@ -101,7 +101,7 @@ class OKGreeter {
```ts twoslash
// @errors: 2540 2540
class Greeter {
- readonly name: string = "world";
+ readonly name: string = 'world';
constructor(otherName?: string) {
if (otherName !== undefined) {
@@ -110,11 +110,11 @@ class Greeter {
}
err() {
- this.name = "不可以";
+ this.name = '不可以';
}
}
const g = new Greeter();
-g.name = "同样不可以";
+g.name = '同样不可以';
```
### 构造函数
@@ -185,7 +185,7 @@ class Derived extends Base {
-类中的函数属性称为_方法_。方法可以使用与函数和构造函数相同的类型注解:
+类中的函数属性称为*方法*。方法可以使用与函数和构造函数相同的类型注解:
```ts twoslash
class Point {
@@ -208,18 +208,18 @@ class Point {
let x: number = 0;
class C {
- x: string = "hello";
+ x: string = 'hello';
m() {
// 这是尝试修改第 1 行的‘x’,而不是类属性
- x = "world";
+ x = 'world';
}
}
```
### Getter / Setter
-类也可以拥有_访问器_:
+类也可以拥有*访问器*:
```ts twoslash
class C {
@@ -299,13 +299,13 @@ interface Pingable {
class Sonar implements Pingable {
ping() {
- console.log("ping!");
+ console.log('ping!');
}
}
class Ball implements Pingable {
pong() {
- console.log("pong!");
+ console.log('pong!');
}
}
```
@@ -314,7 +314,7 @@ class Ball implements Pingable {
#### 注意事项
-重要的是要理解,`implements` 子句仅仅是一个检查,用于判断类是否可以被视为接口类型。它_完全_不会改变类或其方法的类型。一个常见的错误是认为 `implements` 子句会改变类的类型——实际上并不会!
+重要的是要理解,`implements` 子句仅仅是一个检查,用于判断类是否可以被视为接口类型。它*完全*不会改变类或其方法的类型。一个常见的错误是认为 `implements` 子句会改变类的类型——实际上并不会!
```ts twoslash
// @errors: 7006
@@ -325,7 +325,7 @@ interface Checkable {
class NameChecker implements Checkable {
check(s) {
// 注意这里没有错误
- return s.toLowerCase() === "ok";
+ return s.toLowerCase() === 'ok';
// ^?
}
}
@@ -361,14 +361,14 @@ c.y = 10;
```ts twoslash
class Animal {
move() {
- console.log("继续前进!");
+ console.log('继续前进!');
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
- console.log("汪!");
+ console.log('汪!');
}
}
}
@@ -397,7 +397,7 @@ TypeScript 强制要求派生类始终是其基类的子类型。
```ts twoslash
class Base {
greet() {
- console.log("你好,世界!");
+ console.log('你好,世界!');
}
}
@@ -413,7 +413,7 @@ class Derived extends Base {
const d = new Derived();
d.greet();
-d.greet("reader");
+d.greet('reader');
```
派生类必须遵循其基类的约定。请记住,通过基类引用来引用派生类实例是非常常见的做法(并且始终是合法的):
@@ -421,7 +421,7 @@ d.greet("reader");
```ts twoslash
class Base {
greet() {
- console.log("你好,世界!");
+ console.log('你好,世界!');
}
}
class Derived extends Base {}
@@ -439,7 +439,7 @@ b.greet();
// @errors: 2416
class Base {
greet() {
- console.log("你好,世界!");
+ console.log('你好,世界!');
}
}
@@ -500,14 +500,14 @@ JavaScript 类的初始化顺序在某些情况下可能会出人意料。让我
```ts twoslash
class Base {
- name = "基础";
+ name = '基础';
constructor() {
- console.log("我是" + this.name);
+ console.log('我是' + this.name);
}
}
class Derived extends Base {
- name = "派生";
+ name = '派生';
}
// 输出“基础”,而不是“派生”
@@ -541,7 +541,7 @@ class MsgError extends Error {
super(m);
}
sayHello() {
- return "你好" + this.message;
+ return '你好' + this.message;
}
}
```
@@ -563,7 +563,7 @@ class MsgError extends Error {
}
sayHello() {
- return "hello " + this.message;
+ return 'hello ' + this.message;
}
}
```
@@ -583,7 +583,7 @@ class MsgError extends Error {
```ts twoslash
class Greeter {
public greet() {
- console.log("嗨!");
+ console.log('嗨!');
}
}
const g = new Greeter();
@@ -600,17 +600,17 @@ g.greet();
// @errors: 2445
class Greeter {
public greet() {
- console.log("你好," + this.getName());
+ console.log('你好,' + this.getName());
}
protected getName() {
- return "嗨";
+ return '嗨';
}
}
class SpecialGreeter extends Greeter {
public howdy() {
// 可以在这里访问受保护的成员
- console.log("Howdy, " + this.getName());
+ console.log('Howdy, ' + this.getName());
// ^^^^^^^^^^^^^^
}
}
@@ -741,7 +741,7 @@ const s = new MySafe();
console.log(s.secretKey);
```
-`private` 还允许在类型检查期间使用方括号表示法进行访问。这使得对 `private` 声明的字段的访问在单元测试等情况下更容易,缺点是这些字段是_软私有的_,不严格执行私有化。
+`private` 还允许在类型检查期间使用方括号表示法进行访问。这使得对 `private` 声明的字段的访问在单元测试等情况下更容易,缺点是这些字段是*软私有的*,不严格执行私有化。
```ts twoslash
// @errors: 2341
@@ -755,15 +755,15 @@ const s = new MySafe();
console.log(s.secretKey);
// 可以
-console.log(s["secretKey"]);
+console.log(s['secretKey']);
```
-与 TypeScript 的 `private` 不同,JavaScript 的[私有字段](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields)(`#`)在编译后仍然保持私有,并且不提供先前提到的方括号访问等逃逸口,使得它们成为_硬私有_字段。
+与 TypeScript 的 `private` 不同,JavaScript 的[私有字段](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields)(`#`)在编译后仍然保持私有,并且不提供先前提到的方括号访问等逃逸口,使得它们成为*硬私有*字段。
```ts twoslash
class Dog {
#barkAmount = 0;
- personality = "happy";
+ personality = 'happy';
constructor() {}
}
@@ -774,7 +774,7 @@ class Dog {
// @showEmit
class Dog {
#barkAmount = 0;
- personality = "happy";
+ personality = 'happy';
constructor() {}
}
@@ -785,9 +785,9 @@ class Dog {
```ts twoslash
// @target: es2015
// @showEmit
-class Dog{
+class Dog {
#barkAmount = 0;
- personality = "happy";
+ personality = 'happy';
constructor() {}
}
@@ -831,7 +831,7 @@ console.log(MyClass.x);
```ts twoslash
class Base {
static getGreeting() {
- return "你好世界";
+ return '你好世界';
}
}
class Derived extends Base {
@@ -846,7 +846,7 @@ class Derived extends Base {
```ts twoslash
// @errors: 2699
class S {
- static name = "S!";
+ static name = 'S!';
}
```
@@ -854,7 +854,7 @@ class S {
TypeScript(以及 JavaScript)没有类似于 C# 的 `static class` 构造。
-这些构造的存在*仅*是因为这些语言强制要求所有的数据和函数都在类内部;因为 TypeScript 中不存在这种限制,所以也就没有必要使用它们。在 JavaScript/TypeScript 中,通常将只有一个实例的类表示为普通的_对象_。
+这些构造的存在*仅*是因为这些语言强制要求所有的数据和函数都在类内部;因为 TypeScript 中不存在这种限制,所以也就没有必要使用它们。在 JavaScript/TypeScript 中,通常将只有一个实例的类表示为普通的*对象*。
例如,在 TypeScript 中我们不需要“static class”语法,因为普通的对象(甚至是顶级函数)同样可以完成工作:
@@ -878,22 +878,21 @@ const MyHelperObject = {
静态块允许你编写一系列具有自己作用域的语句,这些语句可以访问包含类中的私有字段。这意味着我们可以编写具有所有语句编写功能、没有变量泄漏以及对类内部的完全访问权限的初始化代码。
```ts twoslash
-declare function loadLastInstances(): any[]
+declare function loadLastInstances(): any[];
// ---cut---
class Foo {
- static #count = 0;
+ static #count = 0;
- get count() {
- return Foo.#count;
- }
+ get count() {
+ return Foo.#count;
+ }
- static {
- try {
- const lastInstances = loadLastInstances();
- Foo.#count += lastInstances.length;
- }
- catch {}
- }
+ static {
+ try {
+ const lastInstances = loadLastInstances();
+ Foo.#count += lastInstances.length;
+ } catch {}
+ }
}
```
@@ -909,7 +908,7 @@ class Box {
}
}
-const b = new Box("你好!");
+const b = new Box('你好!');
// ^?
```
@@ -942,14 +941,14 @@ JavaScript 对 `this` 的处理方式确实有些不寻常:
```ts twoslash
class MyClass {
- name = "MyClass";
+ name = 'MyClass';
getName() {
return this.name;
}
}
const c = new MyClass();
const obj = {
- name: "obj",
+ name: 'obj',
getName: c.getName,
};
@@ -973,7 +972,7 @@ console.log(obj.getName());
```ts twoslash
class MyClass {
- name = "MyClass";
+ name = 'MyClass';
getName = () => {
return this.name;
};
@@ -1015,7 +1014,7 @@ TypeScript 检查调用带有 `this` 参数的函数时,确保使用了正确
```ts twoslash
// @errors: 2684
class MyClass {
- name = "MyClass";
+ name = 'MyClass';
getName(this: MyClass) {
return this.name;
}
@@ -1039,12 +1038,11 @@ console.log(g());
在类中,一个特殊的类型 `this` *动态地*指向当前类的类型。让我们看一下它的用法:
-
-```ts twoslash
+```ts
class Box {
- contents: string = "";
+ contents: string = '';
set(value: string) {
-// ^?
+ // ^?
this.contents = value;
return this;
}
@@ -1053,9 +1051,9 @@ class Box {
在这里,TypeScript 推断出 `set` 的返回类型是 `this`,而不是 `Box`。现在让我们创建 `Box` 的一个子类:
-```ts twoslash
+```ts
class Box {
- contents: string = "";
+ contents: string = '';
set(value: string) {
this.contents = value;
return this;
@@ -1064,20 +1062,20 @@ class Box {
// ---cut---
class ClearableBox extends Box {
clear() {
- this.contents = "";
+ this.contents = '';
}
}
const a = new ClearableBox();
-const b = a.set("你好");
+const b = a.set('你好');
// ^?
```
你还可以在参数类型注释中使用 `this`:
-```ts twoslash
+```ts
class Box {
- content: string = "";
+ content: string = '';
sameAs(other: this) {
return other.content === this.content;
}
@@ -1089,14 +1087,14 @@ class Box {
```ts twoslash
// @errors: 2345
class Box {
- content: string = "";
+ content: string = '';
sameAs(other: this) {
return other.content === this.content;
}
}
class DerivedBox extends Box {
- otherContent: string = "?";
+ otherContent: string = '?';
}
const base = new Box();
@@ -1108,8 +1106,7 @@ derived.sameAs(base);
在类和接口的方法中,你可以在返回位置使用 `this is Type`。当与类型缩小(例如 `if` 语句)混合使用时,目标对象的类型将缩小为指定的 `Type`。
-
-```ts twoslash
+```ts
// @strictPropertyInitialization: false
class FileSystemObject {
isFile(): this is FileRep {
@@ -1138,17 +1135,17 @@ interface Networked {
host: string;
}
-const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");
+const fso: FileSystemObject = new FileRep('foo/bar.txt', 'foo');
if (fso.isFile()) {
fso.content;
-// ^?
+ // ^?
} else if (fso.isDirectory()) {
fso.children;
-// ^?
+ // ^?
} else if (fso.isNetworked()) {
fso.host;
-// ^?
+ // ^?
}
```
@@ -1164,7 +1161,7 @@ class Box {
}
const box = new Box();
-box.value = "Gameboy";
+box.value = 'Gameboy';
box.value;
// ^?
@@ -1214,7 +1211,7 @@ const someClass = class {
}
};
-const m = new someClass("你好,世界");
+const m = new someClass('你好,世界');
// ^?
```
@@ -1226,14 +1223,14 @@ JavaScript 类使用 `new` 运算符进行实例化。对于某个类本身的
class Point {
createdAt: number;
x: number;
- y: number
+ y: number;
constructor(x: number, y: number) {
- this.createdAt = Date.now()
+ this.createdAt = Date.now();
this.x = x;
this.y = y;
}
}
-type PointInstance = InstanceType
+type PointInstance = InstanceType;
function moveRight(point: PointInstance) {
point.x += 5;
@@ -1260,7 +1257,7 @@ abstract class Base {
abstract getName(): string;
printName() {
- console.log("你好," + this.getName());
+ console.log('你好,' + this.getName());
}
}
@@ -1277,7 +1274,7 @@ abstract class Base {
// ---cut---
class Derived extends Base {
getName() {
- return "世界";
+ return '世界';
}
}
@@ -1313,7 +1310,7 @@ abstract class Base {
}
class Derived extends Base {
getName() {
- return "";
+ return '';
}
}
// ---cut---
@@ -1342,7 +1339,7 @@ abstract class Base {
}
class Derived extends Base {
getName() {
- return "";
+ return '';
}
}
// ---cut---
diff --git a/zh/handbook-v2/everyday-types.md b/zh/handbook-v2/everyday-types.md
index 0d21a5a8..f05598be 100644
--- a/zh/handbook-v2/everyday-types.md
+++ b/zh/handbook-v2/everyday-types.md
@@ -35,7 +35,7 @@ let obj: any = { x: 0 };
obj.foo();
obj();
obj.bar = 100;
-obj = "hello";
+obj = 'hello';
const n: number = obj;
```
@@ -52,7 +52,7 @@ const n: number = obj;
使用 `const`、`var` 或 `let` 声明变量时,你可以选择性地添加类型注解来显式指定变量的类型:
```ts twoslash
-let myName: string = "Alice";
+let myName: string = 'Alice';
// ^^^^^^^^ 类型注解
```
@@ -63,7 +63,7 @@ let myName: string = "Alice";
```ts twoslash
// 不需要类型注解——“myName”推断为 “string” 类型
-let myName = "Alice";
+let myName = 'Alice';
```
在大多数情况下,你不需要学习推断规则。如果你刚开始使用,尝试少使用一些类型注解——实际上仅需要了解少量的类型注解,就能让 TypeScript 完全理解代码的含义。
@@ -80,7 +80,7 @@ let myName = "Alice";
// 参数类型注解
function greet(name: string) {
// ^^^^^^^^
- console.log("你好," + name.toUpperCase() + "!!");
+ console.log('你好,' + name.toUpperCase() + '!!');
}
```
@@ -118,7 +118,7 @@ function getFavoriteNumber(): number {
```ts twoslash
// @errors: 2551
// 这里没有类型注解,但 TypeScript 可以发现错误
-const names = ["Alice", "Bob", "Eve"];
+const names = ['Alice', 'Bob', 'Eve'];
// 函数的上下文类型推断
names.forEach(function (s) {
@@ -126,7 +126,7 @@ names.forEach(function (s) {
});
// 箭头函数也适用上下文类型推断
-names.forEach((s) => {
+names.forEach(s => {
console.log(s.toUppercase());
});
```
@@ -145,8 +145,8 @@ names.forEach((s) => {
// 参数的类型注解是对象类型
function printCoord(pt: { x: number; y: number }) {
// ^^^^^^^^^^^^^^^^^^^^^^^^
- console.log("坐标的 x 值是 " + pt.x);
- console.log("坐标的 y 值是 " + pt.y);
+ console.log('坐标的 x 值是 ' + pt.x);
+ console.log('坐标的 y 值是 ' + pt.y);
}
printCoord({ x: 3, y: 7 });
```
@@ -164,8 +164,8 @@ function printName(obj: { first: string; last?: string }) {
// ...
}
// 都是有效的
-printName({ first: "Bob" });
-printName({ first: "Alice", last: "Alisson" });
+printName({ first: 'Bob' });
+printName({ first: 'Alice', last: 'Alisson' });
```
在 JavaScript 中,如果访问一个不存在的属性,你会得到 `undefined` 而不是运行时错误。因此,如果你*读取*的是一个可选属性的话,那么在使用它之前,你需要检查其是否为 `undefined`。
@@ -191,19 +191,19 @@ TypeScript 的类型系统允许你使用各种运算符从现有类型构建新
### 定义联合类型
-*联合*(Union)类型是组合类型的一种方式。联合类型是由两个或更多其他类型形成的类型,表示值可以是这些类型中的*任意一个*。我们将每个类型都称为联合的*成员*。
+_联合_(Union)类型是组合类型的一种方式。联合类型是由两个或更多其他类型形成的类型,表示值可以是这些类型中的*任意一个*。我们将每个类型都称为联合的*成员*。
以下是可以操作字符串或数字的函数:
```ts twoslash
// @errors: 2345
function printId(id: number | string) {
- console.log("你的 ID 是:" + id);
+ console.log('你的 ID 是:' + id);
}
// 正常运行
printId(101);
// 正常运行
-printId("202");
+printId('202');
// 错误
printId({ myID: 22342 });
```
@@ -227,7 +227,7 @@ function printId(id: number | string) {
```ts twoslash
function printId(id: number | string) {
- if (typeof id === "string") {
+ if (typeof id === 'string') {
// 在这个分支中,id 的类型是 'string'
console.log(id.toUpperCase());
} else {
@@ -243,10 +243,10 @@ function printId(id: number | string) {
function welcomePeople(x: string[] | string) {
if (Array.isArray(x)) {
// 在这里:'x' 的类型是 'string[]'
- console.log("你好," + x.join(" 和 "));
+ console.log('你好,' + x.join(' 和 '));
} else {
// 在这里:'x' 的类型是 'string'
- console.log("欢迎,孤独旅行者 " + x);
+ console.log('欢迎,孤独旅行者 ' + x);
}
}
```
@@ -282,8 +282,8 @@ type Point = {
// 与前面的示例完全相同
function printCoord(pt: Point) {
- console.log("x 的坐标值是 " + pt.x);
- console.log("y 的坐标值是 " + pt.y);
+ console.log('x 的坐标值是 ' + pt.x);
+ console.log('y 的坐标值是 ' + pt.y);
}
printCoord({ x: 100, y: 100 });
@@ -311,7 +311,7 @@ function sanitizeInput(str: string): UserInputSanitizedString {
let userInput = sanitizeInput(getInput());
// 仍然可以使用字符串重新赋值
-userInput = "新的输入";
+userInput = '新的输入';
```
## 接口
@@ -325,8 +325,8 @@ interface Point {
}
function printCoord(pt: Point) {
- console.log("x 的坐标值是 " + pt.x);
- console.log("y 的坐标值是 " + pt.y);
+ console.log('x 的坐标值是 ' + pt.x);
+ console.log('y 的坐标值是 ' + pt.y);
}
printCoord({ x: 100, y: 100 });
@@ -354,7 +354,7 @@ interface Animal {
interface Bear extends Animal {
honey: boolean
}
-const bear = getBear()
+const bear = getBear()
bear.name
bear.honey
@@ -365,8 +365,8 @@ bear.honey
type Animal = {
name: string
}
-type Bear = Animal & {
- honey: Boolean
+type Bear = Animal & {
+ honey: Boolean
}
const bear = getBear();
bear.name;
@@ -406,7 +406,7 @@ type Window = {
在后面的章节中你会学到更多关于这些概念的知识,所以如果你没有立即理解这些知识,请不要担心。
-- 在 TypeScript 4.2 之前,类型别名命名[*可能* 会出现在错误消息中](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA),有时代替等效的匿名类型(可能需要也可能不需要)。接口在错误消息中将始终被命名。
+- 在 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)在错误消息中,但*只有*在按名称使用时才会出现。
@@ -422,7 +422,7 @@ type Window = {
在这种情况下,你可以使用*类型断言*来指定更具体的类型:
```ts twoslash
-const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
+const myCanvas = document.getElementById('main_canvas') as HTMLCanvasElement;
```
与类型注解类似,类型断言会在编译时移除,不会影响代码的运行行为。
@@ -430,7 +430,7 @@ const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
你也可以使用尖括号语法(除非代码在 `.tsx` 文件中),效果是一样的:
```ts twoslash
-const myCanvas = document.getElementById("main_canvas");
+const myCanvas = document.getElementById('main_canvas');
```
> 提醒:由于类型断言在编译时被移除,因此没有与类型断言相关的运行时检查。
@@ -440,7 +440,7 @@ TypeScript 只允许将类型断言为*更具体*或*更不具体*的类型。
```ts twoslash
// @errors: 2352
-const x = "hello" as number;
+const x = 'hello' as number;
```
有时这个规则可能过于保守,会禁止一些更复杂的强制转换,尽管这些转换可能是有效的。如果遇到这种情况,你可以使用两个断言,先断言为 `any`(或者后面我们会介绍的 `unknown`),然后再断言为目标类型:
@@ -459,13 +459,13 @@ const a = expr as any as T;
可以这样想,JavaScript 提供了不同的声明变量的方式。`var` 和 `let` 都允许改变变量中保存的值,而 `const` 则不允许。这体现在 TypeScript 创建字面类型的方式上。
```ts twoslash
-let changingString = "Hello World";
-changingString = "Olá Mundo";
+let changingString = 'Hello World';
+changingString = 'Olá Mundo';
// `changingString` 可以表示任意可能的字符串,所以 TypeScript 在类型系统中这样描述它
changingString;
// ^?
-const constantString = "Hello World";
+const constantString = 'Hello World';
// `constantString` 只能表示一个可能的字符串,它有字面类型的表示形式
constantString;
// ^?
@@ -475,11 +475,11 @@ constantString;
```ts twoslash
// @errors: 2322
-let x: "hello" = "hello";
+let x: 'hello' = 'hello';
// OK
-x = "hello";
+x = 'hello';
// ...
-x = "howdy";
+x = 'howdy';
```
只能是固定一个值的变量并没有多大用处!
@@ -488,11 +488,11 @@ x = "howdy";
```ts twoslash
// @errors: 2345
-function printText(s: string, alignment: "left" | "right" | "center") {
+function printText(s: string, alignment: 'left' | 'right' | 'center') {
// ...
}
-printText("Hello, world", "left");
-printText("G'day, mate", "centre");
+printText('Hello, world', 'left');
+printText("G'day, mate", 'centre');
```
数字字面类型的工作方式相同:
@@ -510,12 +510,12 @@ function compare(a: string, b: string): -1 | 0 | 1 {
interface Options {
width: number;
}
-function configure(x: Options | "auto") {
+function configure(x: Options | 'auto') {
// ...
}
configure({ width: 100 });
-configure("auto");
-configure("automatic");
+configure('auto');
+configure('automatic');
```
还有一种字面类型:布尔字面类型。只有两种布尔字面类型,`true` 和 `false`。`boolean` 类型本身实际上只是 `true | false` 的联合类型的别名。
@@ -539,9 +539,9 @@ TypeScript 不会认为将 `1` 赋值给之前为 `0` 的字段是一个错误
```ts twoslash
// @errors: 2345
-declare function handleRequest(url: string, method: "GET" | "POST"): void;
+declare function handleRequest(url: string, method: 'GET' | 'POST'): void;
// ---cut---
-const req = { url: "https://example.com", method: "GET" };
+const req = { url: 'https://example.com', method: 'GET' };
handleRequest(req.url, req.method);
```
@@ -552,12 +552,12 @@ handleRequest(req.url, req.method);
1. 可以通过在任一位置添加类型断言来改变推断结果:
```ts twoslash
- declare function handleRequest(url: string, method: "GET" | "POST"): void;
+ declare function handleRequest(url: string, method: 'GET' | 'POST'): void;
// ---cut---
// 改变 1:
- const req = { url: "https://example.com", method: "GET" as "GET" };
+ const req = { url: 'https://example.com', method: 'GET' as 'GET' };
// 改变 2:
- handleRequest(req.url, req.method as "GET");
+ handleRequest(req.url, req.method as 'GET');
```
改变 1 的意思是 "我打算让 `req.method` 始终具有字面量类型 `"GET"`",阻止在之后将 `"GUESS"` 赋值给该字段。
@@ -566,9 +566,9 @@ handleRequest(req.url, req.method);
2. 可以使用 `as const` 将整个对象转换为字面量类型:
```ts twoslash
- declare function handleRequest(url: string, method: "GET" | "POST"): void;
+ declare function handleRequest(url: string, method: 'GET' | 'POST'): void;
// ---cut---
- const req = { url: "https://example.com", method: "GET" } as const;
+ const req = { url: 'https://example.com', method: 'GET' } as const;
handleRequest(req.url, req.method);
```
@@ -582,18 +582,18 @@ TypeScript 也有两个相应的*类型*,名称相同。这些类型的特性
### `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) {
if (x === null) {
// 什么都不做
} else {
- console.log("Hello, " + x.toUpperCase());
+ console.log('Hello, ' + x.toUpperCase());
}
}
```
@@ -641,8 +641,8 @@ JavaScript 中有一个用于通过 `Symbol()` 函数创建全局唯一引用的
```ts twoslash
// @errors: 2367
-const firstName = Symbol("name");
-const secondName = Symbol("name");
+const firstName = Symbol('name');
+const secondName = Symbol('name');
if (firstName === secondName) {
// 永远不会发生
diff --git a/zh/handbook-v2/modules.md b/zh/handbook-v2/modules.md
index b0921b24..f504094f 100644
--- a/zh/handbook-v2/modules.md
+++ b/zh/handbook-v2/modules.md
@@ -50,7 +50,7 @@ export {};
```ts twoslash
// @filename: hello.ts
export default function helloWorld() {
- console.log("Hello, world!");
+ console.log('Hello, world!');
}
```
@@ -59,11 +59,11 @@ export default function helloWorld() {
```ts twoslash
// @filename: hello.ts
export default function helloWorld() {
- console.log("Hello, world!");
+ console.log('Hello, world!');
}
// @filename: index.ts
// ---cut---
-import helloWorld from "./hello.js";
+import helloWorld from './hello.js';
helloWorld();
```
@@ -97,7 +97,7 @@ export function absolute(num: number) {
}
// @filename: app.ts
// ---cut---
-import { pi, phi, absolute } from "./maths.js";
+import { pi, phi, absolute } from './maths.js';
console.log(pi);
const absPhi = absolute(phi);
@@ -113,7 +113,7 @@ const absPhi = absolute(phi);
export var pi = 3.14;
// @filename: app.ts
// ---cut---
-import { pi as π } from "./maths.js";
+import { pi as π } from './maths.js';
console.log(π);
// ^?
@@ -127,7 +127,7 @@ export const pi = 3.14;
export default class RandomNumberGenerator {}
// @filename: app.ts
-import RandomNumberGenerator, { pi as π } from "./maths.js";
+import RandomNumberGenerator, { pi as π } from './maths.js';
RandomNumberGenerator;
// ^?
@@ -150,7 +150,7 @@ export function absolute(num: number) {
}
// ---cut---
// @filename: app.ts
-import * as math from "./maths.js";
+import * as math from './maths.js';
console.log(math.pi);
const positivePhi = math.absolute(math.phi);
@@ -164,9 +164,9 @@ const positivePhi = math.absolute(math.phi);
export var pi = 3.14;
// ---cut---
// @filename: app.ts
-import "./maths.js";
+import './maths.js';
-console.log("3.14");
+console.log('3.14');
```
在这种情况下,`import` 没有任何作用。然而,`maths.ts` 中的所有代码都被执行,这可能触发影响其他对象的副作用。
@@ -185,7 +185,7 @@ export interface Dog {
}
// @filename: app.ts
-import { Cat, Dog } from "./animal.js";
+import { Cat, Dog } from './animal.js';
type Animals = Cat | Dog;
```
@@ -199,15 +199,15 @@ TypeScript 通过两个用来声明类型导入的概念,扩展了 `import`
// @filename: animal.ts
export type Cat = { breed: string; yearOfBirth: number };
export type Dog = { breeds: string[]; yearOfBirth: number };
-export const createCatName = () => "fluffy";
+export const createCatName = () => 'fluffy';
// @filename: valid.ts
-import type { Cat, Dog } from "./animal.js";
+import type { Cat, Dog } from './animal.js';
export type Animals = Cat | Dog;
// @filename: app.ts
// @errors: 1361
-import type { createCatName } from "./animal.js";
+import type { createCatName } from './animal.js';
const name = createCatName();
```
@@ -219,10 +219,10 @@ TypeScript 4.5 还允许在个别导入中使用 `type` 前缀,以指示被导
// @filename: animal.ts
export type Cat = { breed: string; yearOfBirth: number };
export type Dog = { breeds: string[]; yearOfBirth: number };
-export const createCatName = () => "fluffy";
+export const createCatName = () => 'fluffy';
// ---cut---
// @filename: app.ts
-import { createCatName, type Cat, type Dog } from "./animal.js";
+import { createCatName, type Cat, type Dog } from './animal.js';
export type Animals = Cat | Dog;
const name = createCatName();
@@ -238,8 +238,8 @@ TypeScript 具有 ES 模块语法,它与 CommonJS 和 AMD 的 `require` *直
///
// @module: commonjs
// ---cut---
-import fs = require("fs");
-const code = fs.readFileSync("hello.ts", "utf8");
+import fs = require('fs');
+const code = fs.readFileSync('hello.ts', 'utf8');
```
你可以在[模块参考页面](/docs/handbook/modules.html#export--and-import--require)了解更多关于此语法的信息。
@@ -287,7 +287,7 @@ module.exports = {
};
// @filename: index.ts
// ---cut---
-const maths = require("./maths");
+const maths = require('./maths');
maths.pi;
// ^?
```
@@ -311,7 +311,7 @@ module.exports = {
};
// @filename: index.ts
// ---cut---
-const { squareTwo } = require("./maths");
+const { squareTwo } = require('./maths');
squareTwo;
// ^?
```
@@ -348,7 +348,7 @@ TypeScript 包括两种解析策略:经典解析和 Node 解析。经典解析
export const valueOfPi = 3.142;
// @filename: index.ts
// ---cut---
-import { valueOfPi } from "./constants.js";
+import { valueOfPi } from './constants.js';
export const twoPi = valueOfPi * 2;
```
@@ -359,7 +359,7 @@ export const twoPi = valueOfPi * 2;
// @showEmit
// @module: es2020
// @noErrors
-import { valueOfPi } from "./constants.js";
+import { valueOfPi } from './constants.js';
export const twoPi = valueOfPi * 2;
```
@@ -370,7 +370,7 @@ export const twoPi = valueOfPi * 2;
// @showEmit
// @module: commonjs
// @noErrors
-import { valueOfPi } from "./constants.js";
+import { valueOfPi } from './constants.js';
export const twoPi = valueOfPi * 2;
```
@@ -381,7 +381,7 @@ export const twoPi = valueOfPi * 2;
// @showEmit
// @module: umd
// @noErrors
-import { valueOfPi } from "./constants.js";
+import { valueOfPi } from './constants.js';
export const twoPi = valueOfPi * 2;
```
diff --git a/zh/handbook-v2/more-on-functions.md b/zh/handbook-v2/more-on-functions.md
index 41feec98..c6b11aee 100644
--- a/zh/handbook-v2/more-on-functions.md
+++ b/zh/handbook-v2/more-on-functions.md
@@ -8,7 +8,7 @@
```ts twoslash
function greeter(fn: (a: string) => void) {
- fn("Hello, World");
+ fn('Hello, World');
}
function printToConsole(s: string) {
@@ -41,13 +41,13 @@ type DescribableFunction = {
(someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
- console.log(fn.description + " 返回了 " + fn(6));
+ console.log(fn.description + ' 返回了 ' + fn(6));
}
function myFunc(someArg: number) {
return someArg > 3;
}
-myFunc.description = "默认描述";
+myFunc.description = '默认描述';
doSomething(myFunc);
```
@@ -65,7 +65,7 @@ type SomeConstructor = {
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
- return new ctor("你好");
+ return new ctor('你好');
}
```
@@ -104,7 +104,7 @@ function firstElement(arr: Type[]): Type | undefined {
declare function firstElement(arr: Type[]): Type | undefined;
// ---cut---
// s 的类型是 'string'
-const s = firstElement(["a", "b", "c"]);
+const s = firstElement(['a', 'b', 'c']);
// n 的类型是 'number'
const n = firstElement([1, 2, 3]);
// u 的类型是 undefined
@@ -125,7 +125,7 @@ function map(arr: Input[], func: (arg: Input) => Output): Output[
// 参数 'n' 的类型是 'string'
// 'parsed' 的类型是 'number[]'
-const parsed = map(["1", "2", "3"], (n) => parseInt(n));
+const parsed = map(['1', '2', '3'], n => parseInt(n));
```
请注意,在这个示例中,TypeScript 可以(根据给定的 `string` 数组)推断出 `Input` 类型参数的类型,同时根据函数表达式的返回值(`number`)推断出 `Output` 类型参数的类型。
@@ -149,12 +149,12 @@ function longest(a: Type, b: Type) {
// longerArray 的类型为 'number[]'
const longerArray = longest([1, 2], [1, 2, 3]);
// longerString 的类型为 'alice' | 'bob'
-const longerString = longest("alice", "bob");
+const longerString = longest('alice', 'bob');
// 错误!数字没有 'length' 属性
const notOK = longest(10, 100);
```
-这个例子中有几个有趣的地方。我们允许 TypeScript *推断* `longest` 的返回类型。返回类型推断也适用于泛型函数。
+这个例子中有几个有趣的地方。我们允许 TypeScript _推断_ `longest` 的返回类型。返回类型推断也适用于泛型函数。
由于我们将 `Type` 约束为 `{ length: number }`,我们可以访问 `a` 和 `b` 参数的 `.length` 属性。如果没有类型约束,我们将无法访问这些属性,因为这些值可能是没有 length 属性的其他类型。
@@ -210,7 +210,7 @@ function combine(arr1: Type[], arr2: Type[]): Type[] {
// @errors: 2322
declare function combine(arr1: Type[], arr2: Type[]): Type[];
// ---cut---
-const arr = combine([1, 2, 3], ["hello"]);
+const arr = combine([1, 2, 3], ['hello']);
```
然而,如果你打算这样做,可以手动指定 `Type`:
@@ -218,7 +218,7 @@ const arr = combine([1, 2, 3], ["hello"]);
```ts twoslash
declare function combine(arr1: Type[], arr2: Type[]): Type[];
// ---cut---
-const arr = combine([1, 2, 3], ["hello"]);
+const arr = combine([1, 2, 3], ['hello']);
```
### 编写良好的泛型函数的指南
@@ -275,17 +275,17 @@ function filter2 boolean>(
```ts twoslash
function greet(s: Str) {
- console.log("你好," + s);
+ console.log('你好,' + s);
}
-greet("世界");
+greet('世界');
```
我们也可以写一个更简单的版本:
```ts twoslash
function greet(s: string) {
- console.log("你好," + s);
+ console.log('你好,' + s);
}
```
@@ -356,11 +356,11 @@ declare function myForEach(
callback: (arg: any, index?: number) => void
): void;
// ---cut---
-myForEach([1, 2, 3], (a) => console.log(a));
+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
@@ -374,8 +374,7 @@ function myForEach(arr: any[], callback: (arg: any, index?: number) => void) {
然后,TypeScript 将强制执行这个含义,并发出实际上不可能的错误:
-
-```ts twoslash
+```ts
// @errors: 2532 18048
declare function myForEach(
arr: any[],
@@ -452,7 +451,7 @@ function fn(x: string): string;
// 返回类型不正确
function fn(x: number): boolean;
function fn(x: string | number) {
- return "oops";
+ return 'oops';
}
```
@@ -477,9 +476,9 @@ function len(x: any) {
declare function len(s: string): number;
declare function len(arr: any[]): number;
// ---cut---
-len(""); // OK
+len(''); // OK
len([0]); // OK
-len(Math.random() > 0.5 ? "hello" : [0]);
+len(Math.random() > 0.5 ? 'hello' : [0]);
```
由于两个重载具有相同的参数数量和相同的返回类型,我们可以使用非重载版本的函数:
@@ -567,7 +566,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`!
@@ -618,9 +617,9 @@ function fail(msg: string): never {
```ts twoslash
function fn(x: string | number) {
- if (typeof x === "string") {
+ if (typeof x === 'string') {
// 做一些操作
- } else if (typeof x === "number") {
+ } else if (typeof x === 'number') {
// 做另一些操作
} else {
x; // 的类型为 'never'!
@@ -659,7 +658,7 @@ function doSomething(f: Function) {
```ts twoslash
function multiply(n: number, ...m: number[]) {
- return m.map((x) => n * x);
+ return m.map(x => n * x);
}
// 'a' 的值为 [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4);
@@ -786,7 +785,7 @@ const v3 = f3();
const src = [1, 2, 3];
const dst = [0];
-src.forEach((el) => dst.push(el));
+src.forEach(el => dst.push(el));
```
还有另一种特殊情况需要注意,当字面函数定义的返回类型为 `void` 时,该函数必须**不**返回任何内容。
diff --git a/zh/handbook-v2/narrowing.md b/zh/handbook-v2/narrowing.md
index 41d6c718..a903daa4 100644
--- a/zh/handbook-v2/narrowing.md
+++ b/zh/handbook-v2/narrowing.md
@@ -4,7 +4,7 @@
```ts twoslash
function padLeft(padding: number | string, input: string): string {
- throw new Error("尚未实现!");
+ throw new Error('尚未实现!');
}
```
@@ -13,7 +13,7 @@ function padLeft(padding: number | string, input: string): string {
```ts twoslash
// @errors: 2345
function padLeft(padding: number | string, input: string) {
- return " ".repeat(padding) + input;
+ return ' '.repeat(padding) + input;
}
```
@@ -21,8 +21,8 @@ function padLeft(padding: number | string, input: string) {
```ts twoslash
function padLeft(padding: number | string, input: string) {
- if (typeof padding === "number") {
- return " ".repeat(padding) + input;
+ if (typeof padding === 'number') {
+ return ' '.repeat(padding) + input;
}
return padding + input;
}
@@ -36,8 +36,8 @@ function padLeft(padding: number | string, input: string) {
```ts twoslash
function padLeft(padding: number | string, input: string) {
- if (typeof padding === "number") {
- return " ".repeat(padding) + input;
+ if (typeof padding === 'number') {
+ return ' '.repeat(padding) + input;
// ^?
}
return padding + input;
@@ -67,11 +67,11 @@ TypeScript 可以理解几种不同的缩小类型的构造。
```ts twoslash
// @errors: 2531 18047
function printAll(strs: string | string[] | null) {
- if (typeof strs === "object") {
+ if (typeof strs === 'object') {
for (const s of strs) {
console.log(s);
}
- } else if (typeof strs === "string") {
+ } else if (typeof strs === 'string') {
console.log(strs);
} else {
// 什么都不做
@@ -96,7 +96,7 @@ function getUsersOnlineMessage(numUsersOnline: number) {
if (numUsersOnline) {
return `现在有 ${numUsersOnline} 人在线!`;
}
- return "这里没有人。 :(";
+ return '这里没有人。 :(';
}
```
@@ -113,19 +113,19 @@ function getUsersOnlineMessage(numUsersOnline: number) {
```ts twoslash
// 这两个都会得到 ‘true’
-Boolean("hello"); // 类型: boolean, 值: true
-!!"world"; // 类型: true, 值: true
+Boolean('hello'); // 类型: boolean, 值: true
+!!'world'; // 类型: true, 值: true
```
利用这种行为是相当流行的,特别是用于防范 `null` 或 `undefined` 等值。例如,让我们尝试将其应用于我们的 `printAll` 函数。
```ts twoslash
function printAll(strs: string | string[] | null) {
- if (strs && typeof strs === "object") {
+ if (strs && typeof strs === 'object') {
for (const s of strs) {
console.log(s);
}
- } else if (typeof strs === "string") {
+ } else if (typeof strs === 'string') {
console.log(strs);
}
}
@@ -146,11 +146,11 @@ function printAll(strs: string | string[] | null) {
// 继续阅读下去
// !!!!!!!!!!!!!!!!
if (strs) {
- if (typeof strs === "object") {
+ if (typeof strs === 'object') {
for (const s of strs) {
console.log(s);
}
- } else if (typeof strs === "string") {
+ } else if (typeof strs === 'string') {
console.log(strs);
}
}
@@ -171,7 +171,7 @@ function multiplyAll(
if (!values) {
return values;
} else {
- return values.map((x) => x * factor);
+ return values.map(x => x * factor);
}
}
```
@@ -204,12 +204,12 @@ function example(x: string | number, y: string | boolean) {
```ts twoslash
function printAll(strs: string | string[] | null) {
if (strs !== null) {
- if (typeof strs === "object") {
+ if (typeof strs === 'object') {
for (const s of strs) {
// ^?
console.log(s);
}
- } else if (typeof strs === "string") {
+ } else if (typeof strs === 'string') {
console.log(strs);
// ^?
}
@@ -247,7 +247,7 @@ type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
- if ("swim" in animal) {
+ if ('swim' in animal) {
return animal.swim();
}
@@ -257,8 +257,7 @@ function move(animal: Fish | Bird) {
需要强调的是,可选属性在缩小类型时将出现在两个分支中。例如,人类既可以游泳又可以飞行(通过正确的装备),因此应该在 `in` 检查的两个分支中都出现:
-
-```ts twoslash
+```ts
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
@@ -295,13 +294,13 @@ function logValue(x: Date | string) {
正如我们之前提到的,当我们对任何变量进行赋值时,TypeScript 会查看赋值语句的右侧,并相应地缩小左侧的类型。
```ts twoslash
-let x = Math.random() < 0.5 ? 10 : "hello world!";
+let x = Math.random() < 0.5 ? 10 : 'hello world!';
// ^?
x = 1;
console.log(x);
// ^?
-x = "goodbye!";
+x = 'goodbye!';
console.log(x);
// ^?
@@ -313,7 +312,7 @@ console.log(x);
```ts twoslash
// @errors: 2322
-let x = Math.random() < 0.5 ? 10 : "hello world!";
+let x = Math.random() < 0.5 ? 10 : 'hello world!';
// ^?
x = 1;
@@ -331,8 +330,8 @@ console.log(x);
```ts twoslash
function padLeft(padding: number | string, input: string) {
- if (typeof padding === "number") {
- return " ".repeat(padding) + input;
+ if (typeof padding === 'number') {
+ return ' '.repeat(padding) + input;
}
return padding + input;
}
@@ -352,7 +351,7 @@ function example() {
// ^?
if (Math.random() < 0.5) {
- x = "hello";
+ x = 'hello';
console.log(x);
// ^?
} else {
@@ -423,7 +422,7 @@ const underWater2: Fish[] = zoo.filter(isFish) as Fish[];
// 对于更复杂的示例,可能需要重复使用类型断言
const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
- if (pet.name === "sharkey") return false;
+ if (pet.name === 'sharkey') return false;
return isFish(pet);
});
```
@@ -442,7 +441,7 @@ const underWater3: Fish[] = zoo.filter((pet): pet is Fish => {
```ts twoslash
interface Shape {
- kind: "circle" | "square";
+ kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
@@ -453,7 +452,7 @@ interface Shape {
```ts twoslash
// @errors: 2367
interface Shape {
- kind: "circle" | "square";
+ kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
@@ -461,7 +460,7 @@ interface Shape {
// ---cut---
function handleShape(shape: Shape) {
// 出错了!
- if (shape.kind === "rect") {
+ if (shape.kind === 'rect') {
// ...
}
}
@@ -472,7 +471,7 @@ function handleShape(shape: Shape) {
```ts twoslash
// @errors: 2532 18048
interface Shape {
- kind: "circle" | "square";
+ kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
@@ -488,14 +487,14 @@ function getArea(shape: Shape) {
```ts twoslash
// @errors: 2532 18048
interface Shape {
- kind: "circle" | "square";
+ kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
// ---cut---
function getArea(shape: Shape) {
- if (shape.kind === "circle") {
+ if (shape.kind === 'circle') {
return Math.PI * shape.radius ** 2;
}
}
@@ -505,14 +504,14 @@ function getArea(shape: Shape) {
```ts twoslash
interface Shape {
- kind: "circle" | "square";
+ kind: 'circle' | 'square';
radius?: number;
sideLength?: number;
}
// ---cut---
function getArea(shape: Shape) {
- if (shape.kind === "circle") {
+ if (shape.kind === 'circle') {
return Math.PI * shape.radius! ** 2;
}
}
@@ -524,12 +523,12 @@ function getArea(shape: Shape) {
```ts twoslash
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
@@ -543,12 +542,12 @@ type Shape = Circle | Square;
```ts twoslash
// @errors: 2339
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
@@ -566,12 +565,12 @@ function getArea(shape: Shape) {
```ts twoslash
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
@@ -579,7 +578,7 @@ type Shape = Circle | Square;
// ---cut---
function getArea(shape: Shape) {
- if (shape.kind === "circle") {
+ if (shape.kind === 'circle') {
return Math.PI * shape.radius ** 2;
// ^?
}
@@ -594,12 +593,12 @@ function getArea(shape: Shape) {
```ts twoslash
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
@@ -608,10 +607,10 @@ type Shape = Circle | Square;
// ---cut---
function getArea(shape: Shape) {
switch (shape.kind) {
- case "circle":
+ case 'circle':
return Math.PI * shape.radius ** 2;
// ^?
- case "square":
+ case 'square':
return shape.sideLength ** 2;
// ^?
}
@@ -637,12 +636,12 @@ function getArea(shape: Shape) {
```ts twoslash
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
// ---cut---
@@ -650,9 +649,9 @@ type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
- case "circle":
+ case 'circle':
return Math.PI * shape.radius ** 2;
- case "square":
+ case 'square':
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
@@ -666,17 +665,17 @@ function getArea(shape: Shape) {
```ts twoslash
// @errors: 2322
interface Circle {
- kind: "circle";
+ kind: 'circle';
radius: number;
}
interface Square {
- kind: "square";
+ kind: 'square';
sideLength: number;
}
// ---cut---
interface Triangle {
- kind: "triangle";
+ kind: 'triangle';
sideLength: number;
}
@@ -684,9 +683,9 @@ type Shape = Circle | Square | Triangle;
function getArea(shape: Shape) {
switch (shape.kind) {
- case "circle":
+ case 'circle':
return Math.PI * shape.radius ** 2;
- case "square":
+ case 'square':
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
diff --git a/zh/handbook-v2/object-types.md b/zh/handbook-v2/object-types.md
index bb96a4fb..be27de13 100644
--- a/zh/handbook-v2/object-types.md
+++ b/zh/handbook-v2/object-types.md
@@ -455,8 +455,7 @@ interface BasicAddress {
在某些情况下,这已经足够了,但是地址经常会有一个单元号与之关联,比如某个地址对应的建筑物有多个单元。我们可以描述 `AddressWithUnit` 类型。
-
-```ts twoslash
+```ts
interface AddressWithUnit {
name?: string;
unit: string;
diff --git a/zh/handbook/basic-types.md b/zh/handbook/basic-types.md
index 437e126d..1e35caa2 100644
--- a/zh/handbook/basic-types.md
+++ b/zh/handbook/basic-types.md
@@ -2,11 +2,11 @@
## 介绍
-为了让程序有价值,我们需要能够处理最简单的数据单元:数字,字符串,结构体,布尔值等。 TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
+为了让程序有价值,我们需要能够处理最简单的数据单元:数字,字符串,结构体,布尔值等。 TypeScript 支持与 JavaScript 几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
## Boolean
-最基本的数据类型就是简单的true/false值,在JavaScript和TypeScript里叫做`boolean`(其它语言中也一样)。
+最基本的数据类型就是简单的 true/false 值,在 JavaScript 和 TypeScript 里叫做`boolean`(其它语言中也一样)。
```typescript
let isDone: boolean = false;
@@ -14,7 +14,7 @@ let isDone: boolean = false;
## Number
-和JavaScript一样,TypeScript里的所有数字都是浮点数或者大整数 。 这些浮点数的类型是`number`, 而大整数的类型则是 `bigint`。 除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
+和 JavaScript 一样,TypeScript 里的所有数字都是浮点数或者大整数 。 这些浮点数的类型是`number`, 而大整数的类型则是 `bigint`。 除了支持十进制和十六进制字面量,TypeScript 还支持 ECMAScript 2015 中引入的二进制和八进制字面量。
```typescript
let decLiteral: number = 6;
@@ -26,33 +26,38 @@ let bigLiteral: bigint = 100n;
## String
-JavaScript程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样,我们使用`string`表示文本数据类型。 和JavaScript一样,可以使用双引号(`"`)或单引号(`'`)表示字符串。
+JavaScript 程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样,我们使用`string`表示文本数据类型。 和 JavaScript 一样,可以使用双引号(`"`)或单引号(`'`)表示字符串。
```typescript
-let name: string = "bob";
-name = "smith";
+let name: string = 'bob';
+name = 'smith';
```
-你还可以使用_模版字符串_,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围(\` \`),并且以`${ expr }`这种形式嵌入表达式
+你还可以使用*模版字符串*,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围(\` \`),并且以`${ expr }`这种形式嵌入表达式
```typescript
let name: string = `Gene`;
let age: number = 37;
-let sentence: string = `Hello, my name is ${ name }.
+let sentence: string = `Hello, my name is ${name}.
-I'll be ${ age + 1 } years old next month.`;
+I'll be ${age + 1} years old next month.`;
```
这与下面定义`sentence`的方式效果相同:
```typescript
-let sentence: string = "Hello, my name is " + name + ".\n\n" +
- "I'll be " + (age + 1) + " years old next month.";
+let sentence: string =
+ 'Hello, my name is ' +
+ name +
+ '.\n\n' +
+ "I'll be " +
+ (age + 1) +
+ ' years old next month.';
```
## Array
-TypeScript像JavaScript一样可以操作数组元素。 有两种方式可以定义数组。 第一种,可以在元素类型后面接上`[]`,表示由此类型元素组成的一个数组:
+TypeScript 像 JavaScript 一样可以操作数组元素。 有两种方式可以定义数组。 第一种,可以在元素类型后面接上`[]`,表示由此类型元素组成的一个数组:
```typescript
let list: number[] = [1, 2, 3];
@@ -87,41 +92,57 @@ console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'
当访问一个越界的元素会报错。
```typescript
-x[3] = "world"; // Error, Property '3' does not exist on type '[string, number]'.
+x[3] = 'world'; // Error, Property '3' does not exist on type '[string, number]'.
console.log(x[5].toString()); // Error, Property '5' does not exist on type '[string, number]'.
```
## Enum
-`enum`类型是对JavaScript标准数据类型的一个补充。 像C\#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
+`enum`类型是对 JavaScript 标准数据类型的一个补充。 像 C\#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
```typescript
-enum Color {Red, Green, Blue}
+enum Color {
+ Red,
+ Green,
+ Blue,
+}
let c: Color = Color.Green;
```
默认情况下,从`0`开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从`1`开始编号:
```typescript
-enum Color {Red = 1, Green, Blue}
+enum Color {
+ Red = 1,
+ Green,
+ Blue,
+}
let c: Color = Color.Green;
```
或者,全部都采用手动赋值:
```typescript
-enum Color {Red = 1, Green = 2, Blue = 4}
+enum Color {
+ Red = 1,
+ Green = 2,
+ Blue = 4,
+}
let c: Color = Color.Green;
```
-枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:
+枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为 2,但是不确定它映射到 Color 里的哪个名字,我们可以查找相应的名字:
```typescript
-enum Color {Red = 1, Green, Blue}
+enum Color {
+ Red = 1,
+ Green,
+ Blue,
+}
let colorName: string = Color[2];
-console.log(colorName); // 显示'Green'因为上面代码里它的值是2
+console.log(colorName); // 显示'Green'因为上面代码里它的值是2
```
## Unknown
@@ -130,7 +151,7 @@ console.log(colorName); // 显示'Green'因为上面代码里它的值是2
```typescript
let notSure: unknown = 4;
-notSure = "maybe a string instead";
+notSure = 'maybe a string instead';
// OK, definitely a boolean
notSure = false;
@@ -151,7 +172,7 @@ if (maybe === true) {
const aString: string = maybe;
}
-if (typeof maybe === "string") {
+if (typeof maybe === 'string') {
// TypeScript knows that maybe is a string
const aString: string = maybe;
// So, it cannot be a boolean
@@ -165,7 +186,7 @@ if (typeof maybe === "string") {
```typescript
let notSure: any = 4;
-notSure = "maybe a string instead";
+notSure = 'maybe a string instead';
notSure = false; // okay, definitely a boolean
```
@@ -185,7 +206,7 @@ prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object
当你只知道一部分数据的类型时,`any`类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据:
```typescript
-let list: any[] = [1, true, "free"];
+let list: any[] = [1, true, 'free'];
list[1] = 100;
```
@@ -196,7 +217,7 @@ list[1] = 100;
```typescript
function warnUser(): void {
- console.log("This is my warning message");
+ console.log('This is my warning message');
}
```
@@ -208,7 +229,7 @@ let unusable: void = undefined;
## Null 和 Undefined
-TypeScript里,`undefined`和`null`两者各自有自己的类型分别叫做`undefined`和`null`。 和`void`相似,它们的本身的类型用处不是很大:
+TypeScript 里,`undefined`和`null`两者各自有自己的类型分别叫做`undefined`和`null`。 和`void`相似,它们的本身的类型用处不是很大:
```typescript
// Not much else we can assign to these variables!
@@ -218,7 +239,7 @@ let n: null = null;
默认情况下`null`和`undefined`是所有类型的子类型。 就是说你可以把`null`和`undefined`赋值给`number`类型的变量。
-然而,当你指定了`--strictNullChecks`标记,`null`和`undefined`只能赋值给`any`和它们各自的类型(有一个例外是`undefined`还可以赋值给`void`类型)。 这能避免_很多_常见的问题。 也许在某处你想传入一个`string`或`null`或`undefined`,你可以使用联合类型`string | null | undefined`。
+然而,当你指定了`--strictNullChecks`标记,`null`和`undefined`只能赋值给`any`和它们各自的类型(有一个例外是`undefined`还可以赋值给`void`类型)。 这能避免*很多*常见的问题。 也许在某处你想传入一个`string`或`null`或`undefined`,你可以使用联合类型`string | null | undefined`。
联合类型是高级主题,我们会在以后的章节里讨论它。
@@ -228,25 +249,24 @@ let n: null = null;
`never`类型表示的是那些永不存在的值的类型。 例如,`never`类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是`never`类型,当它们被永不为真的类型保护所约束时。
-`never`类型是任何类型的子类型,也可以赋值给任何类型;然而,_没有_类型是`never`的子类型或可以赋值给`never`类型(除了`never`本身之外)。 即使`any`也不可以赋值给`never`。
+`never`类型是任何类型的子类型,也可以赋值给任何类型;然而,*没有*类型是`never`的子类型或可以赋值给`never`类型(除了`never`本身之外)。 即使`any`也不可以赋值给`never`。
下面是一些返回`never`类型的函数:
```typescript
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
- throw new Error(message);
+ throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
- return error("Something failed");
+ return error('Something failed');
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
- while (true) {
- }
+ while (true) {}
}
```
@@ -254,7 +274,7 @@ function infiniteLoop(): never {
`object`表示非原始类型,也就是除`number`,`string`,`boolean`,`bigint`,`symbol`,`null`或`undefined`之外的类型。
-使用`object`类型,就可以更好的表示像`Object.create`这样的API。例如:
+使用`object`类型,就可以更好的表示像`Object.create`这样的 API。例如:
```typescript
declare function create(o: object | null): void;
@@ -263,21 +283,21 @@ create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
-create("string"); // Error
+create('string'); // Error
create(false); // Error
create(undefined); // Error
```
## 类型断言
-有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
+有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
-通过_类型断言_这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。
+通过*类型断言*这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法:
```typescript
-let someValue: any = "this is a string";
+let someValue: any = 'this is a string';
let strLength: number = (someValue).length;
```
@@ -285,16 +305,16 @@ let strLength: number = (someValue).length;
另一个为`as`语法:
```typescript
-let someValue: any = "this is a string";
+let someValue: any = 'this is a string';
let strLength: number = (someValue as string).length;
```
-两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在TypeScript里使用JSX时,只有`as`语法断言是被允许的。
+两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在 TypeScript 里使用 JSX 时,只有`as`语法断言是被允许的。
## 关于`let`
-你可能已经注意到了,我们使用`let`关键字来代替大家所熟悉的JavaScript关键字`var`。 `let`是ES2015引入的关键字,它比`var`更加安全,因此被看做是声明变量的标准方式。 我们会在以后详细介绍它,很多常见的问题都可以通过使用`let`来解决,所以尽可能地使用`let`来代替`var`吧。
+你可能已经注意到了,我们使用`let`关键字来代替大家所熟悉的 JavaScript 关键字`var`。 `let`是 ES2015 引入的关键字,它比`var`更加安全,因此被看做是声明变量的标准方式。 我们会在以后详细介绍它,很多常见的问题都可以通过使用`let`来解决,所以尽可能地使用`let`来代替`var`吧。
## 关于 Number, String, Boolean, Symbol 和 Object
@@ -303,19 +323,18 @@ let strLength: number = (someValue as string).length;
```typescript
// @errors: 2339
function reverse(s: String): String {
- return s.split("").reverse().join("");
+ return s.split('').reverse().join('');
}
-reverse("hello world");
+reverse('hello world');
```
相对地,我们应该使用 `number`、`string`、`boolean`、`object` 和 `symbol`
```typescript
function reverse(s: string): string {
- return s.split("").reverse().join("");
+ return s.split('').reverse().join('');
}
-reverse("hello world");
+reverse('hello world');
```
-
diff --git a/zh/handbook/classes.md b/zh/handbook/classes.md
index a753cc36..f9a18b2c 100644
--- a/zh/handbook/classes.md
+++ b/zh/handbook/classes.md
@@ -2,7 +2,7 @@
## 介绍
-传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。 从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。 使用TypeScript,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。
+传统的 JavaScript 程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。 从 ECMAScript 2015,也就是 ECMAScript 6 开始,JavaScript 程序员将能够使用基于类的面向对象的方式。 使用 TypeScript,我们允许开发者现在就使用这些特性,并且编译后的 JavaScript 可以在所有主流浏览器和平台上运行,而不需要等到下个 JavaScript 版本。
## 类
@@ -10,19 +10,19 @@
```typescript
class Greeter {
- greeting: string;
- constructor(message: string) {
- this.greeting = message;
- }
- greet() {
- return "Hello, " + this.greeting;
- }
+ greeting: string;
+ constructor(message: string) {
+ this.greeting = message;
+ }
+ greet() {
+ return 'Hello, ' + this.greeting;
+ }
}
-let greeter = new Greeter("world");
+let greeter = new Greeter('world');
```
-如果你使用过C\#或Java,你会对这种语法非常熟悉。 我们声明一个`Greeter`类。这个类有3个成员:一个叫做`greeting`的属性,一个构造函数和一个`greet`方法。
+如果你使用过 C\#或 Java,你会对这种语法非常熟悉。 我们声明一个`Greeter`类。这个类有 3 个成员:一个叫做`greeting`的属性,一个构造函数和一个`greet`方法。
你会注意到,我们在引用任何一个类成员的时候都用了`this`。 它表示我们访问的是类的成员。
@@ -30,21 +30,21 @@ let greeter = new Greeter("world");
## 继承
-在TypeScript里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。
+在 TypeScript 里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。
看下面的例子:
```typescript
class Animal {
- move(distanceInMeters: number = 0) {
- console.log(`Animal moved ${distanceInMeters}m.`);
- }
+ move(distanceInMeters: number = 0) {
+ console.log(`Animal moved ${distanceInMeters}m.`);
+ }
}
class Dog extends Animal {
- bark() {
- console.log('Woof! Woof!');
- }
+ bark() {
+ console.log('Woof! Woof!');
+ }
}
const dog = new Dog();
@@ -53,7 +53,7 @@ dog.move(10);
dog.bark();
```
-这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,`Dog`是一个_派生类_,它派生自`Animal`_基类_,通过`extends`关键字。 派生类通常被称作_子类_,基类通常被称作_超类_。
+这个例子展示了最基本的继承:类从基类中继承了属性和方法。 这里,`Dog`是一个*派生类*,它派生自`Animal`_基类_,通过`extends`关键字。 派生类通常被称作*子类*,基类通常被称作*超类*。
因为`Dog`继承了`Animal`的功能,因此我们可以创建一个`Dog`的实例,它能够`bark()`和`move()`。
@@ -61,31 +61,37 @@ dog.bark();
```typescript
class Animal {
- name: string;
- constructor(theName: string) { this.name = theName; }
- move(distanceInMeters: number = 0) {
- console.log(`${this.name} moved ${distanceInMeters}m.`);
- }
+ name: string;
+ constructor(theName: string) {
+ this.name = theName;
+ }
+ move(distanceInMeters: number = 0) {
+ console.log(`${this.name} moved ${distanceInMeters}m.`);
+ }
}
class Snake extends Animal {
- constructor(name: string) { super(name); }
- move(distanceInMeters = 5) {
- console.log("Slithering...");
- super.move(distanceInMeters);
- }
+ constructor(name: string) {
+ super(name);
+ }
+ move(distanceInMeters = 5) {
+ console.log('Slithering...');
+ super.move(distanceInMeters);
+ }
}
class Horse extends Animal {
- constructor(name: string) { super(name); }
- move(distanceInMeters = 45) {
- console.log("Galloping...");
- super.move(distanceInMeters);
- }
+ constructor(name: string) {
+ super(name);
+ }
+ move(distanceInMeters = 45) {
+ console.log('Galloping...');
+ super.move(distanceInMeters);
+ }
}
-let sam = new Snake("Sammy the Python");
-let tom: Animal = new Horse("Tommy the Palomino");
+let sam = new Snake('Sammy the Python');
+let tom: Animal = new Horse('Tommy the Palomino');
sam.move();
tom.move(34);
@@ -93,7 +99,7 @@ tom.move(34);
这个例子展示了一些上面没有提到的特性。 这一次,我们使用`extends`关键字创建了`Animal`的两个子类:`Horse`和`Snake`。
-与前一个例子的不同点是,派生类包含了一个构造函数,它_必须_调用`super()`,它会执行基类的构造函数。 而且,在构造函数里访问`this`的属性之前,我们_一定_要调用`super()`。 这个是TypeScript强制执行的一条重要规则。
+与前一个例子的不同点是,派生类包含了一个构造函数,它*必须*调用`super()`,它会执行基类的构造函数。 而且,在构造函数里访问`this`的属性之前,我们*一定*要调用`super()`。 这个是 TypeScript 强制执行的一条重要规则。
这个例子演示了如何在子类里可以重写父类的方法。 `Snake`类和`Horse`类都创建了`move`方法,它们重写了从`Animal`继承来的`move`方法,使得`move`方法根据不同的类而具有不同的功能。 注意,即使`tom`被声明为`Animal`类型,但因为它的值是`Horse`,调用`tom.move(34)`时,它会调用`Horse`里重写的方法:
@@ -108,17 +114,19 @@ Tommy the Palomino moved 34m.
### 默认为`public`
-在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用`public`来做修饰;例如,C\#要求必须明确地使用`public`指定成员是可见的。 在TypeScript里,成员都默认为`public`。
+在上面的例子里,我们可以自由的访问程序里定义的成员。 如果你对其它语言中的类比较了解,就会注意到我们在之前的代码里并没有使用`public`来做修饰;例如,C\#要求必须明确地使用`public`指定成员是可见的。 在 TypeScript 里,成员都默认为`public`。
你也可以明确的将一个成员标记成`public`。 我们可以用下面的方式来重写上面的`Animal`类:
```typescript
class Animal {
- public name: string;
- public constructor(theName: string) { this.name = theName; }
- public move(distanceInMeters: number) {
- console.log(`${this.name} moved ${distanceInMeters}m.`);
- }
+ public name: string;
+ public constructor(theName: string) {
+ this.name = theName;
+ }
+ public move(distanceInMeters: number) {
+ console.log(`${this.name} moved ${distanceInMeters}m.`);
+ }
}
```
@@ -128,14 +136,16 @@ class Animal {
```typescript
class Animal {
- private name: string;
- constructor(theName: string) { this.name = theName; }
+ private name: string;
+ constructor(theName: string) {
+ this.name = theName;
+ }
}
-new Animal("Cat").name; // 错误: 'name' 是私有的.
+new Animal('Cat').name; // 错误: 'name' 是私有的.
```
-TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。
+TypeScript 使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。
然而,当我们比较带有`private`或`protected`成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个`private`成员,那么只有当另外一个类型中也存在这样一个`private`成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于`protected`成员也使用这个规则。
@@ -143,22 +153,28 @@ TypeScript使用的是结构性类型系统。 当我们比较两种不同的类
```typescript
class Animal {
- private name: string;
- constructor(theName: string) { this.name = theName; }
+ private name: string;
+ constructor(theName: string) {
+ this.name = theName;
+ }
}
class Rhino extends Animal {
- constructor() { super("Rhino"); }
+ constructor() {
+ super('Rhino');
+ }
}
class Employee {
- private name: string;
- constructor(theName: string) { this.name = theName; }
+ private name: string;
+ constructor(theName: string) {
+ this.name = theName;
+ }
}
-let animal = new Animal("Goat");
+let animal = new Animal('Goat');
let rhino = new Rhino();
-let employee = new Employee("Bob");
+let employee = new Employee('Bob');
animal = rhino;
animal = employee; // 错误: Animal 与 Employee 不兼容.
@@ -172,24 +188,26 @@ animal = employee; // 错误: Animal 与 Employee 不兼容.
```typescript
class Person {
- protected name: string;
- constructor(name: string) { this.name = name; }
+ protected name: string;
+ constructor(name: string) {
+ this.name = name;
+ }
}
class Employee extends Person {
- private department: string;
+ private department: string;
- constructor(name: string, department: string) {
- super(name)
- this.department = department;
- }
+ constructor(name: string, department: string) {
+ super(name);
+ this.department = department;
+ }
- public getElevatorPitch() {
- return `Hello, my name is ${this.name} and I work in ${this.department}.`;
- }
+ public getElevatorPitch() {
+ return `Hello, my name is ${this.name} and I work in ${this.department}.`;
+ }
}
-let howard = new Employee("Howard", "Sales");
+let howard = new Employee('Howard', 'Sales');
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误
```
@@ -200,54 +218,56 @@ console.log(howard.name); // 错误
```typescript
class Person {
- protected name: string;
- protected constructor(theName: string) { this.name = theName; }
+ protected name: string;
+ protected constructor(theName: string) {
+ this.name = theName;
+ }
}
// Employee 能够继承 Person
class Employee extends Person {
- private department: string;
+ private department: string;
- constructor(name: string, department: string) {
- super(name);
- this.department = department;
- }
+ constructor(name: string, department: string) {
+ super(name);
+ this.department = department;
+ }
- public getElevatorPitch() {
- return `Hello, my name is ${this.name} and I work in ${this.department}.`;
- }
+ public getElevatorPitch() {
+ return `Hello, my name is ${this.name} and I work in ${this.department}.`;
+ }
}
-let howard = new Employee("Howard", "Sales");
-let john = new Person("John"); // 错误: 'Person' 的构造函数是被保护的.
+let howard = new Employee('Howard', 'Sales');
+let john = new Person('John'); // 错误: 'Person' 的构造函数是被保护的.
```
-## readonly修饰符
+## readonly 修饰符
你可以使用`readonly`关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
```typescript
class Octopus {
- readonly name: string;
- readonly numberOfLegs: number = 8;
- constructor (theName: string) {
- this.name = theName;
- }
+ readonly name: string;
+ readonly numberOfLegs: number = 8;
+ constructor(theName: string) {
+ this.name = theName;
+ }
}
-let dad = new Octopus("Man with the 8 strong legs");
-dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
+let dad = new Octopus('Man with the 8 strong legs');
+dad.name = 'Man with the 3-piece suit'; // 错误! name 是只读的.
```
### 参数属性
-在上面的例子中,我们不得不在在`Person`类里定义一个只读成员`name`和一个构造函数参数`theName`。这样做是为了在`Octopus`构造函数被执行后,就可以访问`theName`的值。 这种情况经常会遇到。_参数属性_可以方便地让我们在一个地方定义并初始化一个成员。 下面的例子是对之前`Animal`类的修改版,使用了参数属性:
+在上面的例子中,我们不得不在在`Person`类里定义一个只读成员`name`和一个构造函数参数`theName`。这样做是为了在`Octopus`构造函数被执行后,就可以访问`theName`的值。 这种情况经常会遇到。*参数属性*可以方便地让我们在一个地方定义并初始化一个成员。 下面的例子是对之前`Animal`类的修改版,使用了参数属性:
```typescript
class Animal {
- constructor(private name: string) { }
- move(distanceInMeters: number) {
- console.log(`${this.name} moved ${distanceInMeters}m.`);
- }
+ constructor(private name: string) {}
+ move(distanceInMeters: number) {
+ console.log(`${this.name} moved ${distanceInMeters}m.`);
+ }
}
```
@@ -257,19 +277,19 @@ class Animal {
## 存取器
-TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
+TypeScript 支持通过 getters/setters 来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
下面来看如何把一个简单的类改写成使用`get`和`set`。 首先,我们从一个没有使用存取器的例子开始。
```typescript
class Employee {
- fullName: string;
+ fullName: string;
}
let employee = new Employee();
-employee.fullName = "Bob Smith";
+employee.fullName = 'Bob Smith';
if (employee.fullName) {
- console.log(employee.fullName);
+ console.log(employee.fullName);
}
```
@@ -283,25 +303,25 @@ if (employee.fullName) {
const fullNameMaxLength = 10;
class Employee {
- private _fullName: string;
-
- get fullName(): string {
- return this._fullName;
- }
+ private _fullName: string;
- set fullName(newName: string) {
- if (newName && newName.length > fullNameMaxLength) {
- throw new Error("fullName has a max length of " + fullNameMaxLength);
- }
+ get fullName(): string {
+ return this._fullName;
+ }
- this._fullName = newName;
+ set fullName(newName: string) {
+ if (newName && newName.length > fullNameMaxLength) {
+ throw new Error('fullName has a max length of ' + fullNameMaxLength);
}
+
+ this._fullName = newName;
+ }
}
let employee = new Employee();
-employee.fullName = "Bob Smith";
+employee.fullName = 'Bob Smith';
if (employee.fullName) {
- alert(employee.fullName);
+ alert(employee.fullName);
}
```
@@ -309,7 +329,7 @@ if (employee.fullName) {
对于存取器有下面几点需要注意的:
-首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。 其次,只带有`get`不带有`set`的存取器自动被推断为`readonly`。 这在从代码生成`.d.ts`文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
+首先,存取器要求你将编译器设置为输出 ECMAScript 5 或更高。 不支持降级到 ECMAScript 3。 其次,只带有`get`不带有`set`的存取器自动被推断为`readonly`。 这在从代码生成`.d.ts`文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。
## 静态属性
@@ -317,20 +337,20 @@ if (employee.fullName) {
```typescript
class Grid {
- static origin = {x: 0, y: 0};
- calculateDistanceFromOrigin(point: {x: number; y: number;}) {
- let xDist = (point.x - Grid.origin.x);
- let yDist = (point.y - Grid.origin.y);
- return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
- }
- constructor (public scale: number) { }
+ static origin = { x: 0, y: 0 };
+ calculateDistanceFromOrigin(point: { x: number; y: number }) {
+ let xDist = point.x - Grid.origin.x;
+ let yDist = point.y - Grid.origin.y;
+ return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
+ }
+ constructor(public scale: number) {}
}
-let grid1 = new Grid(1.0); // 1x scale
-let grid2 = new Grid(5.0); // 5x scale
+let grid1 = new Grid(1.0); // 1x scale
+let grid2 = new Grid(5.0); // 5x scale
-console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
-console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
+console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }));
+console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }));
```
## 抽象类
@@ -339,10 +359,10 @@ console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
```typescript
abstract class Animal {
- abstract makeSound(): void;
- move(): void {
- console.log("roaming the earth...");
- }
+ abstract makeSound(): void;
+ move(): void {
+ console.log('roaming the earth...');
+ }
}
```
@@ -350,30 +370,27 @@ abstract class Animal {
```typescript
abstract class Department {
+ constructor(public name: string) {}
- constructor(public name: string) {
- }
-
- printName(): void {
- console.log('Department name: ' + this.name);
- }
+ printName(): void {
+ console.log('Department name: ' + this.name);
+ }
- abstract printMeeting(): void; // 必须在派生类中实现
+ abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
+ constructor() {
+ super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
+ }
- constructor() {
- super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
- }
+ printMeeting(): void {
+ console.log('The Accounting Department meets each Monday at 10am.');
+ }
- printMeeting(): void {
- console.log('The Accounting Department meets each Monday at 10am.');
- }
-
- generateReports(): void {
- console.log('Generating accounting reports...');
- }
+ generateReports(): void {
+ console.log('Generating accounting reports...');
+ }
}
let department: Department; // 允许创建一个对抽象类型的引用
@@ -388,60 +405,59 @@ department.generateReports(); // 错误: 方法在声明的抽象类中不存在
### 构造函数
-当你在TypeScript里声明了一个类的时候,实际上同时声明了很多东西。 首先就是类的_实例_的类型。
+当你在 TypeScript 里声明了一个类的时候,实际上同时声明了很多东西。 首先就是类的*实例*的类型。
```typescript
class Greeter {
- greeting: string;
- constructor(message: string) {
- this.greeting = message;
- }
- greet() {
- return "Hello, " + this.greeting;
- }
+ greeting: string;
+ constructor(message: string) {
+ this.greeting = message;
+ }
+ greet() {
+ return 'Hello, ' + this.greeting;
+ }
}
let greeter: Greeter;
-greeter = new Greeter("world");
+greeter = new Greeter('world');
console.log(greeter.greet());
```
这里,我们写了`let greeter: Greeter`,意思是`Greeter`类的实例的类型是`Greeter`。 这对于用过其它面向对象语言的程序员来讲已经是老习惯了。
-我们也创建了一个叫做_构造函数_的值。 这个函数会在我们使用`new`创建类实例的时候被调用。 下面我们来看看,上面的代码被编译成JavaScript后是什么样子的:
+我们也创建了一个叫做*构造函数*的值。 这个函数会在我们使用`new`创建类实例的时候被调用。 下面我们来看看,上面的代码被编译成 JavaScript 后是什么样子的:
```typescript
let Greeter = (function () {
- function Greeter(message) {
- this.greeting = message;
- }
- Greeter.prototype.greet = function () {
- return "Hello, " + this.greeting;
- };
- return Greeter;
+ function Greeter(message) {
+ this.greeting = message;
+ }
+ Greeter.prototype.greet = function () {
+ return 'Hello, ' + this.greeting;
+ };
+ return Greeter;
})();
let greeter;
-greeter = new Greeter("world");
+greeter = new Greeter('world');
console.log(greeter.greet());
```
-上面的代码里,`let Greeter`将被赋值为构造函数。 当我们调用`new`并执行了这个函数后,便会得到一个类的实例。 这个构造函数也包含了类的所有静态属性。 换个角度说,我们可以认为类具有_实例部分_与_静态部分_这两个部分。
+上面的代码里,`let Greeter`将被赋值为构造函数。 当我们调用`new`并执行了这个函数后,便会得到一个类的实例。 这个构造函数也包含了类的所有静态属性。 换个角度说,我们可以认为类具有*实例部分*与*静态部分*这两个部分。
让我们稍微改写一下这个例子,看看它们之间的区别:
```typescript
class Greeter {
- static standardGreeting = "Hello, there";
- greeting: string;
- greet() {
- if (this.greeting) {
- return "Hello, " + this.greeting;
- }
- else {
- return Greeter.standardGreeting;
- }
+ static standardGreeting = 'Hello, there';
+ greeting: string;
+ greet() {
+ if (this.greeting) {
+ return 'Hello, ' + this.greeting;
+ } else {
+ return Greeter.standardGreeting;
}
+ }
}
let greeter1: Greeter;
@@ -449,7 +465,7 @@ greeter1 = new Greeter();
console.log(greeter1.greet());
let greeterMaker: typeof Greeter = Greeter;
-greeterMaker.standardGreeting = "Hey there!";
+greeterMaker.standardGreeting = 'Hey there!';
let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet());
@@ -457,7 +473,7 @@ console.log(greeter2.greet());
这个例子里,`greeter1`与之前看到的一样。 我们实例化`Greeter`类,并使用这个对象。 与我们之前看到的一样。
-再之后,我们直接使用类。 我们创建了一个叫做`greeterMaker`的变量。 这个变量保存了这个类或者说保存了类构造函数。 然后我们使用`typeof Greeter`,意思是取Greeter类的类型,而不是实例的类型。 或者更确切的说,"告诉我`Greeter`标识符的类型",也就是构造函数的类型。 这个类型包含了类的所有静态成员和构造函数。 之后,就和前面一样,我们在`greeterMaker`上使用`new`,创建`Greeter`的实例。
+再之后,我们直接使用类。 我们创建了一个叫做`greeterMaker`的变量。 这个变量保存了这个类或者说保存了类构造函数。 然后我们使用`typeof Greeter`,意思是取 Greeter 类的类型,而不是实例的类型。 或者更确切的说,"告诉我`Greeter`标识符的类型",也就是构造函数的类型。 这个类型包含了类的所有静态成员和构造函数。 之后,就和前面一样,我们在`greeterMaker`上使用`new`,创建`Greeter`的实例。
### 把类当做接口使用
@@ -465,14 +481,13 @@ console.log(greeter2.greet());
```typescript
class Point {
- x: number;
- y: number;
+ x: number;
+ y: number;
}
interface Point3d extends Point {
- z: number;
+ z: number;
}
-let point3d: Point3d = {x: 1, y: 2, z: 3};
+let point3d: Point3d = { x: 1, y: 2, z: 3 };
```
-
diff --git a/zh/handbook/enums.md b/zh/handbook/enums.md
index e6189fa1..4a60008e 100644
--- a/zh/handbook/enums.md
+++ b/zh/handbook/enums.md
@@ -2,7 +2,7 @@
## 枚举
-使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。
+使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript 支持数字的和基于字符串的枚举。
### 数字枚举
@@ -10,10 +10,10 @@
```typescript
enum Direction {
- Up = 1,
- Down,
- Left,
- Right
+ Up = 1,
+ Down,
+ Left,
+ Right,
}
```
@@ -23,10 +23,10 @@ enum Direction {
```typescript
enum Direction {
- Up,
- Down,
- Left,
- Right,
+ Up,
+ Down,
+ Left,
+ Right,
}
```
@@ -36,23 +36,23 @@ enum Direction {
```typescript
enum Response {
- No = 0,
- Yes = 1,
+ No = 0,
+ Yes = 1,
}
function respond(recipient: string, message: Response): void {
- // ...
+ // ...
}
-respond("Princess Caroline", Response.Yes)
+respond('Princess Caroline', Response.Yes);
```
数字枚举可以被混入到[计算过的和常量成员(如下所示)](enums.md#computed-and-constant-members)。 简短地说,没有初始化器的成员要么在首位,要么必须在用数值常量或其他常量枚举成员初始化的数值枚举之后。 换句话说,下面的情况是不被允许的:
```typescript
enum E {
- A = getSomeValue(),
- B, // Error! Enum member must have initializer.
+ A = getSomeValue(),
+ B, // Error! Enum member must have initializer.
}
```
@@ -62,10 +62,10 @@ enum E {
```typescript
enum Direction {
- Up = "UP",
- Down = "DOWN",
- Left = "LEFT",
- Right = "RIGHT",
+ Up = 'UP',
+ Down = 'DOWN',
+ Left = 'LEFT',
+ Right = 'RIGHT',
}
```
@@ -77,37 +77,45 @@ enum Direction {
```typescript
enum BooleanLikeHeterogeneousEnum {
- No = 0,
- Yes = "YES",
+ No = 0,
+ Yes = 'YES',
}
```
-除非你真的想要利用JavaScript运行时的行为,否则我们不建议这样做。
+除非你真的想要利用 JavaScript 运行时的行为,否则我们不建议这样做。
### 计算的和常量成员
-每个枚举成员都带有一个值,它可以是_常量_或_计算出来的_。 当满足如下条件时,枚举成员被当作是常量:
+每个枚举成员都带有一个值,它可以是*常量*或*计算出来的*。 当满足如下条件时,枚举成员被当作是常量:
-* 它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值`0`:
+- 它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值`0`:
```typescript
// E.X is constant:
- enum E { X }
+ enum E {
+ X,
+ }
```
-* 它不带有初始化器且它之前的枚举成员是一个_数字_常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加1。
+- 它不带有初始化器且它之前的枚举成员是一个*数字*常量。 这种情况下,当前枚举成员的值为它上一个枚举成员的值加 1。
```typescript
// All enum members in 'E1' and 'E2' are constant.
- enum E1 { X, Y, Z }
+ enum E1 {
+ X,
+ Y,
+ Z,
+ }
enum E2 {
- A = 1, B, C
+ A = 1,
+ B,
+ C,
}
```
-* 枚举成员使用_常量枚举表达式_初始化。 常量枚举表达式是TypeScript表达式的子集,它可以在编译阶段求值。 当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:
+- 枚举成员使用*常量枚举表达式*初始化。 常量枚举表达式是 TypeScript 表达式的子集,它可以在编译阶段求值。 当一个表达式满足下面条件之一时,它就是一个常量枚举表达式:
1. 一个枚举表达式字面量(主要是字符串字面量或数字字面量)
2. 一个对之前定义的常量枚举成员的引用(可以是在不同的枚举类型中定义的)
@@ -121,13 +129,13 @@ enum BooleanLikeHeterogeneousEnum {
```typescript
enum FileAccess {
- // constant members
- None,
- Read = 1 << 1,
- Write = 1 << 2,
- ReadWrite = Read | Write,
- // computed member
- G = "123".length
+ // constant members
+ None,
+ Read = 1 << 1,
+ Write = 1 << 2,
+ ReadWrite = Read | Write,
+ // computed member
+ G = '123'.length,
}
```
@@ -135,53 +143,53 @@ enum FileAccess {
存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员。 字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为
-* 任何字符串字面量(例如:`"foo"`,`"bar"`,`"baz"`)
-* 任何数字字面量(例如:`1`, `100`)
-* 应用了一元`-`符号的数字字面量(例如:`-1`, `-100`)
+- 任何字符串字面量(例如:`"foo"`,`"bar"`,`"baz"`)
+- 任何数字字面量(例如:`1`, `100`)
+- 应用了一元`-`符号的数字字面量(例如:`-1`, `-100`)
当所有枚举成员都拥有字面量枚举值时,它就带有了一种特殊的语义。
-首先,枚举成员成为了类型! 例如,我们可以说某些成员_只能_是枚举成员的值:
+首先,枚举成员成为了类型! 例如,我们可以说某些成员*只能*是枚举成员的值:
```typescript
enum ShapeKind {
- Circle,
- Square,
+ Circle,
+ Square,
}
interface Circle {
- kind: ShapeKind.Circle;
- radius: number;
+ kind: ShapeKind.Circle;
+ radius: number;
}
interface Square {
- kind: ShapeKind.Square;
- sideLength: number;
+ kind: ShapeKind.Square;
+ sideLength: number;
}
let c: Circle = {
- kind: ShapeKind.Square, // Error! Type 'ShapeKind.Square' is not assignable to type 'ShapeKind.Circle'.
- radius: 100,
-}
+ kind: ShapeKind.Square, // Error! Type 'ShapeKind.Square' is not assignable to type 'ShapeKind.Circle'.
+ radius: 100,
+};
```
-另一个变化是枚举类型本身变成了每个枚举成员的_联合_。 虽然我们还没有讨论[联合类型](advanced-types.md#union-types),但你只要知道通过联合枚举,类型系统能够利用这样一个事实,它可以知道枚举里的值的集合。 因此,TypeScript能够捕获在比较值的时候犯的愚蠢的错误。 例如:
+另一个变化是枚举类型本身变成了每个枚举成员的*联合*。 虽然我们还没有讨论[联合类型](advanced-types.md#union-types),但你只要知道通过联合枚举,类型系统能够利用这样一个事实,它可以知道枚举里的值的集合。 因此,TypeScript 能够捕获在比较值的时候犯的愚蠢的错误。 例如:
```typescript
enum E {
- Foo,
- Bar,
+ Foo,
+ Bar,
}
function f(x: E) {
- if (x !== E.Foo || x !== E.Bar) {
- // ~~~~~~~~~~~
- // Error! This condition will always return 'true' since the types 'E.Foo' and 'E.Bar' have no overlap.
- }
+ if (x !== E.Foo || x !== E.Bar) {
+ // ~~~~~~~~~~~
+ // Error! This condition will always return 'true' since the types 'E.Foo' and 'E.Bar' have no overlap.
+ }
}
```
-这个例子里,我们先检查`x`是否不是`E.Foo`。 如果通过了这个检查,然后`||`会发生短路效果,`if`语句体里的内容会被执行。 然而,这个检查没有通过,那么`x`则_只能_为`E.Foo`,因此没理由再去检查它是否为`E.Bar`。
+这个例子里,我们先检查`x`是否不是`E.Foo`。 如果通过了这个检查,然后`||`会发生短路效果,`if`语句体里的内容会被执行。 然而,这个检查没有通过,那么`x`则*只能*为`E.Foo`,因此没理由再去检查它是否为`E.Bar`。
### 运行时的枚举
@@ -189,7 +197,9 @@ function f(x: E) {
```typescript
enum E {
- X, Y, Z
+ X,
+ Y,
+ Z,
}
```
@@ -197,7 +207,7 @@ enum E {
```typescript
function f(obj: { X: number }) {
- return obj.X;
+ return obj.X;
}
// 没问题,因为 'E'包含一个数值型属性'X'。
@@ -210,7 +220,10 @@ f(E);
```typescript
enum LogLevel {
- ERROR, WARN, INFO, DEBUG
+ ERROR,
+ WARN,
+ INFO,
+ DEBUG,
}
/**
@@ -220,34 +233,34 @@ enum LogLevel {
type LogLevelStrings = keyof typeof LogLevel;
function printImportant(key: LogLevelStrings, message: string) {
- const num = LogLevel[key];
- if (num <= LogLevel.WARN) {
- console.log('Log level key is: ', key);
- console.log('Log level value is: ', num);
- console.log('Log level message is: ', message);
- }
+ const num = LogLevel[key];
+ if (num <= LogLevel.WARN) {
+ console.log('Log level key is: ', key);
+ console.log('Log level value is: ', num);
+ console.log('Log level message is: ', message);
+ }
}
printImportant('ERROR', 'This is a message');
```
#### 反向映射
-除了创建一个以属性名做为对象成员的对象之外,数字枚举成员还具有了_反向映射_,从枚举值到枚举名字。 例如,在下面的例子中:
+除了创建一个以属性名做为对象成员的对象之外,数字枚举成员还具有了*反向映射*,从枚举值到枚举名字。 例如,在下面的例子中:
```typescript
enum Enum {
- A
+ A,
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
```
-TypeScript可能会将这段代码编译为下面的JavaScript:
+TypeScript 可能会将这段代码编译为下面的 JavaScript:
```javascript
var Enum;
(function (Enum) {
- Enum[Enum["A"] = 0] = "A";
+ Enum[(Enum['A'] = 0)] = 'A';
})(Enum || (Enum = {}));
var a = Enum.A;
var nameOfA = Enum[a]; // "A"
@@ -255,7 +268,7 @@ var nameOfA = Enum[a]; // "A"
生成的代码中,枚举类型被编译成一个对象,它包含了正向映射(`name` -> `value`)和反向映射(`value` -> `name`)。 引用枚举成员总会生成为对属性访问并且永远也不会内联代码。
-要注意的是_不会_为字符串枚举成员生成反向映射。
+要注意的是*不会*为字符串枚举成员生成反向映射。
#### `const`枚举
@@ -263,8 +276,8 @@ var nameOfA = Enum[a]; // "A"
```typescript
const enum Enum {
- A = 1,
- B = A * 2
+ A = 1,
+ B = A * 2,
}
```
@@ -272,13 +285,18 @@ const enum Enum {
```typescript
const enum Directions {
- Up,
- Down,
- Left,
- Right
+ Up,
+ Down,
+ Left,
+ Right,
}
-let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
+let directions = [
+ Directions.Up,
+ Directions.Down,
+ Directions.Left,
+ Directions.Right,
+];
```
生成后的代码为:
@@ -293,11 +311,10 @@ var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
```typescript
declare enum Enum {
- A = 1,
- B,
- C = 2
+ A = 1,
+ B,
+ C = 2,
}
```
外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常量成员。 对于非常量的外部枚举而言,没有初始化方法时被当做需要经过计算的。
-
diff --git a/zh/handbook/functions.md b/zh/handbook/functions.md
index 8ab6b372..1167b3c7 100644
--- a/zh/handbook/functions.md
+++ b/zh/handbook/functions.md
@@ -2,31 +2,33 @@
## 介绍
-函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义_行为_的地方。 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。
+函数是 JavaScript 应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在 TypeScript 里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义*行为*的地方。 TypeScript 为 JavaScript 函数添加了额外的功能,让我们可以更容易地使用。
## 函数
-和JavaScript一样,TypeScript函数可以创建有名字的函数和匿名函数。 你可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数。
+和 JavaScript 一样,TypeScript 函数可以创建有名字的函数和匿名函数。 你可以随意选择适合应用程序的方式,不论是定义一系列 API 函数还是只使用一次的函数。
-通过下面的例子可以迅速回想起这两种JavaScript中的函数:
+通过下面的例子可以迅速回想起这两种 JavaScript 中的函数:
```typescript
// Named function
function add(x, y) {
- return x + y;
+ return x + y;
}
// Anonymous function
-let myAdd = function(x, y) { return x + y; };
+let myAdd = function (x, y) {
+ return x + y;
+};
```
-在JavaScript里,函数可以使用函数体外部的变量。 当函数这么做时,我们说它‘捕获’了这些变量。 至于为什么可以这样做以及其中的利弊超出了本文的范围,但是深刻理解这个机制对学习JavaScript和TypeScript会很有帮助。
+在 JavaScript 里,函数可以使用函数体外部的变量。 当函数这么做时,我们说它‘捕获’了这些变量。 至于为什么可以这样做以及其中的利弊超出了本文的范围,但是深刻理解这个机制对学习 JavaScript 和 TypeScript 会很有帮助。
```typescript
let z = 100;
function addToZ(x, y) {
- return x + y + z;
+ return x + y + z;
}
```
@@ -38,108 +40,119 @@ function addToZ(x, y) {
```typescript
function add(x: number, y: number): number {
- return x + y;
+ return x + y;
}
-let myAdd = function(x: number, y: number): number { return x + y; };
+let myAdd = function (x: number, y: number): number {
+ return x + y;
+};
```
-我们可以给每个参数添加类型之后再为函数本身添加返回值类型。 TypeScript能够根据返回语句自动推断出返回值类型,因此我们通常省略它。
+我们可以给每个参数添加类型之后再为函数本身添加返回值类型。 TypeScript 能够根据返回语句自动推断出返回值类型,因此我们通常省略它。
### 书写完整函数类型
现在我们已经为函数指定了类型,下面让我们写出函数的完整类型。
```typescript
-let myAdd: (x:number, y:number) => number =
- function(x: number, y: number): number { return x + y; };
+let myAdd: (x: number, y: number) => number = function (
+ x: number,
+ y: number
+): number {
+ return x + y;
+};
```
函数类型包含两部分:参数类型和返回值类型。 当写出完整函数类型的时候,这两部分都是需要的。 我们以参数列表的形式写出参数类型,为每个参数指定一个名字和类型。 这个名字只是为了增加可读性。 我们也可以这么写:
```typescript
-let myAdd: (baseValue: number, increment: number) => number =
- function(x: number, y: number): number { return x + y; };
+let myAdd: (baseValue: number, increment: number) => number = function (
+ x: number,
+ y: number
+): number {
+ return x + y;
+};
```
只要参数类型是匹配的,那么就认为它是有效的函数类型,而不在乎参数名是否正确。
第二部分是返回值类型。 对于返回值,我们在函数和返回值类型之前使用\(`=>`\)符号,使之清晰明了。 如之前提到的,返回值类型是函数类型的必要部分,如果函数没有返回任何值,你也必须指定返回值类型为`void`而不能留空。
-函数的类型只是由参数类型和返回值组成的。 函数中使用的捕获变量不会体现在类型里。 实际上,这些变量是函数的隐藏状态并不是组成API的一部分。
+函数的类型只是由参数类型和返回值组成的。 函数中使用的捕获变量不会体现在类型里。 实际上,这些变量是函数的隐藏状态并不是组成 API 的一部分。
### 推断类型
-尝试这个例子的时候,你会注意到,就算仅在等式的一侧带有类型,TypeScript编译器仍可正确识别类型:
+尝试这个例子的时候,你会注意到,就算仅在等式的一侧带有类型,TypeScript 编译器仍可正确识别类型:
```typescript
// myAdd has the full function type
-let myAdd = function(x: number, y: number): number { return x + y; };
+let myAdd = function (x: number, y: number): number {
+ return x + y;
+};
// The parameters `x` and `y` have the type number
-let myAdd: (baseValue: number, increment: number) => number =
- function(x, y) { return x + y; };
+let myAdd: (baseValue: number, increment: number) => number = function (x, y) {
+ return x + y;
+};
```
这叫做“按上下文归类”,是类型推论的一种。 它帮助我们更好地为程序指定类型。
## 可选参数和默认参数
-TypeScript里的每个函数参数都是必须的。 这不是指不能传递`null`或`undefined`作为参数,而是说编译器检查用户是否为每个参数都传入了值。 编译器还会假设只有这些参数会被传递进函数。 简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。
+TypeScript 里的每个函数参数都是必须的。 这不是指不能传递`null`或`undefined`作为参数,而是说编译器检查用户是否为每个参数都传入了值。 编译器还会假设只有这些参数会被传递进函数。 简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。
```typescript
function buildName(firstName: string, lastName: string) {
- return firstName + " " + lastName;
+ return firstName + ' ' + lastName;
}
-let result1 = buildName("Bob"); // error, too few parameters
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // ah, just right
+let result1 = buildName('Bob'); // error, too few parameters
+let result2 = buildName('Bob', 'Adams', 'Sr.'); // error, too many parameters
+let result3 = buildName('Bob', 'Adams'); // ah, just right
```
-JavaScript里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined。 在TypeScript里我们可以在参数名旁使用`?`实现可选参数的功能。 比如,我们想让last name是可选的:
+JavaScript 里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是 undefined。 在 TypeScript 里我们可以在参数名旁使用`?`实现可选参数的功能。 比如,我们想让 last name 是可选的:
```typescript
function buildName(firstName: string, lastName?: string) {
- if (lastName)
- return firstName + " " + lastName;
- else
- return firstName;
+ if (lastName) return firstName + ' ' + lastName;
+ else return firstName;
}
-let result1 = buildName("Bob"); // works correctly now
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // ah, just right
+let result1 = buildName('Bob'); // works correctly now
+let result2 = buildName('Bob', 'Adams', 'Sr.'); // error, too many parameters
+let result3 = buildName('Bob', 'Adams'); // ah, just right
```
-可选参数必须跟在必须参数后面。 如果上例我们想让first name是可选的,那么就必须调整它们的位置,把first name放在后面。
+可选参数必须跟在必须参数后面。 如果上例我们想让 first name 是可选的,那么就必须调整它们的位置,把 first name 放在后面。
-在TypeScript里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是`undefined`时。 它们叫做有默认初始化值的参数。 让我们修改上例,把last name的默认值设置为`"Smith"`。
+在 TypeScript 里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是`undefined`时。 它们叫做有默认初始化值的参数。 让我们修改上例,把 last name 的默认值设置为`"Smith"`。
```typescript
-function buildName(firstName: string, lastName = "Smith") {
- return firstName + " " + lastName;
+function buildName(firstName: string, lastName = 'Smith') {
+ return firstName + ' ' + lastName;
}
-let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
-let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"
-let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result4 = buildName("Bob", "Adams"); // ah, just right
+let result1 = buildName('Bob'); // works correctly now, returns "Bob Smith"
+let result2 = buildName('Bob', undefined); // still works, also returns "Bob Smith"
+let result3 = buildName('Bob', 'Adams', 'Sr.'); // error, too many parameters
+let result4 = buildName('Bob', 'Adams'); // ah, just right
```
在所有必须参数后面的带默认初始化的参数都是可选的,与可选参数一样,在调用函数的时候可以省略。 也就是说可选参数与末尾的默认参数共享参数类型。
```typescript
function buildName(firstName: string, lastName?: string) {
- // ...
+ // ...
}
```
和
```typescript
-function buildName(firstName: string, lastName = "Smith") {
- // ...
+function buildName(firstName: string, lastName = 'Smith') {
+ // ...
}
```
@@ -148,28 +161,28 @@ function buildName(firstName: string, lastName = "Smith") {
与普通可选参数不同的是,带默认值的参数不需要放在必须参数的后面。 如果带默认值的参数出现在必须参数前面,用户必须明确的传入`undefined`值来获得默认值。 例如,我们重写最后一个例子,让`firstName`是带默认值的参数:
```typescript
-function buildName(firstName = "Will", lastName: string) {
- return firstName + " " + lastName;
+function buildName(firstName = 'Will', lastName: string) {
+ return firstName + ' ' + lastName;
}
-let result1 = buildName("Bob"); // error, too few parameters
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams"
-let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams"
+let result1 = buildName('Bob'); // error, too few parameters
+let result2 = buildName('Bob', 'Adams', 'Sr.'); // error, too many parameters
+let result3 = buildName('Bob', 'Adams'); // okay and returns "Bob Adams"
+let result4 = buildName(undefined, 'Adams'); // okay and returns "Will Adams"
```
## 剩余参数
-必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在JavaScript里,你可以使用`arguments`来访问所有传入的参数。
+必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在 JavaScript 里,你可以使用`arguments`来访问所有传入的参数。
-在TypeScript里,你可以把所有参数收集到一个变量里:
+在 TypeScript 里,你可以把所有参数收集到一个变量里:
```typescript
function buildName(firstName: string, ...restOfName: string[]) {
- return firstName + " " + restOfName.join(" ");
+ return firstName + ' ' + restOfName.join(' ');
}
-let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
+let employeeName = buildName('Joseph', 'Samuel', 'Lucas', 'MacKinzie');
```
剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是你在省略号(`...`)后面给定的名字,你可以在函数体内使用这个数组。
@@ -178,7 +191,7 @@ let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
```typescript
function buildName(firstName: string, ...restOfName: string[]) {
- return firstName + " " + restOfName.join(" ");
+ return firstName + ' ' + restOfName.join(' ');
}
let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
@@ -186,60 +199,60 @@ let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
## `this`
-学习如何在JavaScript里正确使用`this`就好比一场成年礼。 由于TypeScript是JavaScript的超集,TypeScript程序员也需要弄清`this`工作机制并且当有bug的时候能够找出错误所在。 幸运的是,TypeScript能通知你错误地使用了`this`的地方。 如果你想了解JavaScript里的`this`是如何工作的,那么首先阅读Yehuda Katz写的[Understanding JavaScript Function Invocation and "this"](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)。 Yehuda的文章详细的阐述了`this`的内部工作原理,因此我们这里只做简单介绍。
+学习如何在 JavaScript 里正确使用`this`就好比一场成年礼。 由于 TypeScript 是 JavaScript 的超集,TypeScript 程序员也需要弄清`this`工作机制并且当有 bug 的时候能够找出错误所在。 幸运的是,TypeScript 能通知你错误地使用了`this`的地方。 如果你想了解 JavaScript 里的`this`是如何工作的,那么首先阅读 Yehuda Katz 写的[Understanding JavaScript Function Invocation and "this"](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/)。 Yehuda 的文章详细的阐述了`this`的内部工作原理,因此我们这里只做简单介绍。
### `this`和箭头函数
-JavaScript里,`this`的值在函数被调用的时候才会指定。 这是个既强大又灵活的特点,但是你需要花点时间弄清楚函数调用的上下文是什么。 但众所周知,这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候。
+JavaScript 里,`this`的值在函数被调用的时候才会指定。 这是个既强大又灵活的特点,但是你需要花点时间弄清楚函数调用的上下文是什么。 但众所周知,这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候。
下面看一个例子:
```typescript
let deck = {
- suits: ["hearts", "spades", "clubs", "diamonds"],
- cards: Array(52),
- createCardPicker: function() {
- return function() {
- let pickedCard = Math.floor(Math.random() * 52);
- let pickedSuit = Math.floor(pickedCard / 13);
-
- return {suit: this.suits[pickedSuit], card: pickedCard % 13};
- }
- }
-}
+ suits: ['hearts', 'spades', 'clubs', 'diamonds'],
+ cards: Array(52),
+ createCardPicker: function () {
+ return function () {
+ let pickedCard = Math.floor(Math.random() * 52);
+ let pickedSuit = Math.floor(pickedCard / 13);
+
+ return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
+ };
+ },
+};
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
+alert('card: ' + pickedCard.card + ' of ' + pickedCard.suit);
```
可以看到`createCardPicker`是个函数,并且它又返回了一个函数。 如果我们尝试运行这个程序,会发现它并没有弹出对话框而是报错了。 因为`createCardPicker`返回的函数里的`this`被设置成了`window`而不是`deck`对象。 因为我们只是独立地调用了`cardPicker()`。 顶级的非方法式调用会将`this`视为`window`。 (注意:在严格模式下,`this`为`undefined`而不是`window`)。
-为了解决这个问题,我们可以在函数被返回时就绑好正确的`this`。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 我们需要改变函数表达式来使用ECMAScript 6箭头语法。 箭头函数能保存函数创建时的`this`值,而不是调用时的值:
+为了解决这个问题,我们可以在函数被返回时就绑好正确的`this`。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 我们需要改变函数表达式来使用 ECMAScript 6 箭头语法。 箭头函数能保存函数创建时的`this`值,而不是调用时的值:
```typescript
let deck = {
- suits: ["hearts", "spades", "clubs", "diamonds"],
- cards: Array(52),
- createCardPicker: function() {
- // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
- return () => {
- let pickedCard = Math.floor(Math.random() * 52);
- let pickedSuit = Math.floor(pickedCard / 13);
-
- return {suit: this.suits[pickedSuit], card: pickedCard % 13};
- }
- }
-}
+ suits: ['hearts', 'spades', 'clubs', 'diamonds'],
+ cards: Array(52),
+ createCardPicker: function () {
+ // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
+ return () => {
+ let pickedCard = Math.floor(Math.random() * 52);
+ let pickedSuit = Math.floor(pickedCard / 13);
+
+ return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
+ };
+ },
+};
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
+alert('card: ' + pickedCard.card + ' of ' + pickedCard.suit);
```
-更好事情是,TypeScript会警告你犯了一个错误,如果你给编译器设置了`--noImplicitThis`标记。 它会指出`this.suits[pickedSuit]`里的`this`的类型为`any`。
+更好事情是,TypeScript 会警告你犯了一个错误,如果你给编译器设置了`--noImplicitThis`标记。 它会指出`this.suits[pickedSuit]`里的`this`的类型为`any`。
### `this`参数
@@ -247,7 +260,7 @@ alert("card: " + pickedCard.card + " of " + pickedCard.suit);
```typescript
function f(this: void) {
- // make sure `this` is unusable in this standalone function
+ // make sure `this` is unusable in this standalone function
}
```
@@ -255,35 +268,35 @@ function f(this: void) {
```typescript
interface Card {
- suit: string;
- card: number;
+ suit: string;
+ card: number;
}
interface Deck {
- suits: string[];
- cards: number[];
- createCardPicker(this: Deck): () => Card;
+ suits: string[];
+ cards: number[];
+ createCardPicker(this: Deck): () => Card;
}
let deck: Deck = {
- suits: ["hearts", "spades", "clubs", "diamonds"],
- cards: Array(52),
- // NOTE: The function now explicitly specifies that its callee must be of type Deck
- createCardPicker: function(this: Deck) {
- return () => {
- let pickedCard = Math.floor(Math.random() * 52);
- let pickedSuit = Math.floor(pickedCard / 13);
-
- return {suit: this.suits[pickedSuit], card: pickedCard % 13};
- }
- }
-}
+ suits: ['hearts', 'spades', 'clubs', 'diamonds'],
+ cards: Array(52),
+ // NOTE: The function now explicitly specifies that its callee must be of type Deck
+ createCardPicker: function (this: Deck) {
+ return () => {
+ let pickedCard = Math.floor(Math.random() * 52);
+ let pickedSuit = Math.floor(pickedCard / 13);
+
+ return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
+ };
+ },
+};
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
+alert('card: ' + pickedCard.card + ' of ' + pickedCard.suit);
```
-现在TypeScript知道`createCardPicker`期望在某个`Deck`对象上调用。 也就是说`this`是`Deck`类型的,而非`any`,因此`--noImplicitThis`不会报错了。
+现在 TypeScript 知道`createCardPicker`期望在某个`Deck`对象上调用。 也就是说`this`是`Deck`类型的,而非`any`,因此`--noImplicitThis`不会报错了。
#### 回调函数里的`this`参数
@@ -291,7 +304,7 @@ alert("card: " + pickedCard.card + " of " + pickedCard.suit);
```typescript
interface UIElement {
- addClickListener(onclick: (this: void, e: Event) => void): void;
+ addClickListener(onclick: (this: void, e: Event) => void): void;
}
```
@@ -299,25 +312,25 @@ interface UIElement {
```typescript
class Handler {
- info: string;
- onClickBad(this: Handler, e: Event) {
- // oops, used this here. using this callback would crash at runtime
- this.info = e.message;
- }
+ info: string;
+ onClickBad(this: Handler, e: Event) {
+ // oops, used this here. using this callback would crash at runtime
+ this.info = e.message;
+ }
}
let h = new Handler();
uiElement.addClickListener(h.onClickBad); // error!
```
-指定了`this`类型后,你显式声明`onClickBad`必须在`Handler`的实例上调用。 然后TypeScript会检测到`addClickListener`要求函数带有`this: void`。 改变`this`类型来修复这个错误:
+指定了`this`类型后,你显式声明`onClickBad`必须在`Handler`的实例上调用。 然后 TypeScript 会检测到`addClickListener`要求函数带有`this: void`。 改变`this`类型来修复这个错误:
```typescript
class Handler {
- info: string;
- onClickGood(this: void, e: Event) {
- // can't use this here because it's of type void!
- console.log('clicked!');
- }
+ info: string;
+ onClickGood(this: void, e: Event) {
+ // can't use this here because it's of type void!
+ console.log('clicked!');
+ }
}
let h = new Handler();
uiElement.addClickListener(h.onClickGood);
@@ -327,8 +340,10 @@ uiElement.addClickListener(h.onClickGood);
```typescript
class Handler {
- info: string;
- onClickGood = (e: Event) => { this.info = e.message }
+ info: string;
+ onClickGood = (e: Event) => {
+ this.info = e.message;
+ };
}
```
@@ -336,31 +351,35 @@ class Handler {
## 重载
-JavaScript本身是个动态语言。 JavaScript里函数根据传入不同的参数而返回不同类型的数据是很常见的。
+JavaScript 本身是个动态语言。 JavaScript 里函数根据传入不同的参数而返回不同类型的数据是很常见的。
```typescript
-let suits = ["hearts", "spades", "clubs", "diamonds"];
+let suits = ['hearts', 'spades', 'clubs', 'diamonds'];
function pickCard(x): any {
- // Check to see if we're working with an object/array
- // if so, they gave us the deck and we'll pick the card
- if (typeof x == "object") {
- let pickedCard = Math.floor(Math.random() * x.length);
- return pickedCard;
- }
- // Otherwise just let them pick the card
- else if (typeof x == "number") {
- let pickedSuit = Math.floor(x / 13);
- return { suit: suits[pickedSuit], card: x % 13 };
- }
+ // Check to see if we're working with an object/array
+ // if so, they gave us the deck and we'll pick the card
+ if (typeof x == 'object') {
+ let pickedCard = Math.floor(Math.random() * x.length);
+ return pickedCard;
+ }
+ // Otherwise just let them pick the card
+ else if (typeof x == 'number') {
+ let pickedSuit = Math.floor(x / 13);
+ return { suit: suits[pickedSuit], card: x % 13 };
+ }
}
-let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
+let myDeck = [
+ { suit: 'diamonds', card: 2 },
+ { suit: 'spades', card: 10 },
+ { suit: 'hearts', card: 4 },
+];
let pickedCard1 = myDeck[pickCard(myDeck)];
-alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
+alert('card: ' + pickedCard1.card + ' of ' + pickedCard1.suit);
let pickedCard2 = pickCard(15);
-alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
+alert('card: ' + pickedCard2.card + ' of ' + pickedCard2.suit);
```
`pickCard`方法根据传入参数的不同会返回两种不同的类型。 如果传入的是代表纸牌的对象,函数作用是从中抓一张牌。 如果用户想抓牌,我们告诉他抓到了什么牌。 但是这怎么在类型系统里表示呢。
@@ -368,35 +387,38 @@ alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
方法是为同一个函数提供多个函数类型定义来进行函数重载。 编译器会根据这个列表去处理函数的调用。 下面我们来重载`pickCard`函数。
```typescript
-let suits = ["hearts", "spades", "clubs", "diamonds"];
+let suits = ['hearts', 'spades', 'clubs', 'diamonds'];
-function pickCard(x: {suit: string; card: number; }[]): number;
-function pickCard(x: number): {suit: string; card: number; };
+function pickCard(x: { suit: string; card: number }[]): number;
+function pickCard(x: number): { suit: string; card: number };
function pickCard(x): any {
- // Check to see if we're working with an object/array
- // if so, they gave us the deck and we'll pick the card
- if (typeof x == "object") {
- let pickedCard = Math.floor(Math.random() * x.length);
- return pickedCard;
- }
- // Otherwise just let them pick the card
- else if (typeof x == "number") {
- let pickedSuit = Math.floor(x / 13);
- return { suit: suits[pickedSuit], card: x % 13 };
- }
+ // Check to see if we're working with an object/array
+ // if so, they gave us the deck and we'll pick the card
+ if (typeof x == 'object') {
+ let pickedCard = Math.floor(Math.random() * x.length);
+ return pickedCard;
+ }
+ // Otherwise just let them pick the card
+ else if (typeof x == 'number') {
+ let pickedSuit = Math.floor(x / 13);
+ return { suit: suits[pickedSuit], card: x % 13 };
+ }
}
-let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
+let myDeck = [
+ { suit: 'diamonds', card: 2 },
+ { suit: 'spades', card: 10 },
+ { suit: 'hearts', card: 4 },
+];
let pickedCard1 = myDeck[pickCard(myDeck)];
-alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
+alert('card: ' + pickedCard1.card + ' of ' + pickedCard1.suit);
let pickedCard2 = pickCard(15);
-alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
+alert('card: ' + pickedCard2.card + ' of ' + pickedCard2.suit);
```
这样改变后,重载的`pickCard`函数在调用的时候会进行正确的类型检查。
-为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
+为了让编译器能够选择正确的检查类型,它与 JavaScript 里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
注意,`function pickCard(x): any`并不是重载列表的一部分,因此这里只有两个重载:一个是接收对象另一个接收数字。 以其它参数调用`pickCard`会产生错误。
-
diff --git a/zh/handbook/generics.md b/zh/handbook/generics.md
index c248fabb..07ff68e8 100644
--- a/zh/handbook/generics.md
+++ b/zh/handbook/generics.md
@@ -2,19 +2,21 @@
## 介绍
-软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
+软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
-在像C\#和Java这样的语言中,可以使用`泛型`来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
+在像 C\#和 Java 这样的语言中,可以使用`泛型`来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
-## 泛型之Hello World
+## 泛型之 Hello World
-下面来创建第一个使用泛型的例子:identity函数。 这个函数会返回任何传入它的值。 你可以把这个函数当成是`echo`命令。
+下面来创建第一个使用泛型的例子:identity 函数。
+这个函数会返回任何传入它的值。
+你可以把这个函数当成是`echo`命令。
不用泛型的话,这个函数可能是下面这样:
```typescript
function identity(arg: number): number {
- return arg;
+ return arg;
}
```
@@ -22,39 +24,39 @@ function identity(arg: number): number {
```typescript
function identity(arg: any): any {
- return arg;
+ return arg;
}
```
使用`any`类型会导致这个函数可以接收任何类型的`arg`参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。 如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。
-因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了_类型变量_,它是一种特殊的变量,只用于表示类型而不是值。
+因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了*类型变量*,它是一种特殊的变量,只用于表示类型而不是值。
```typescript
function identity(arg: T): T {
- return arg;
+ return arg;
}
```
-我们给identity添加了类型变量`T`。 `T`帮助我们捕获用户传入的类型(比如:`number`),之后我们就可以使用这个类型。 之后我们再次使用了`T`当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
+我们给 identity 添加了类型变量`T`。 `T`帮助我们捕获用户传入的类型(比如:`number`),之后我们就可以使用这个类型。 之后我们再次使用了`T`当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
我们把这个版本的`identity`函数叫做泛型,因为它可以适用于多个类型。 不同于使用`any`,它不会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。
我们定义了泛型函数后,可以用两种方法使用。 第一种是,传入所有的参数,包含类型参数:
```typescript
-let output = identity("myString"); // type of output will be 'string'
+let output = identity('myString'); // type of output will be 'string'
```
这里我们明确的指定了`T`是`string`类型,并做为一个参数传给函数,使用了`<>`括起来而不是`()`。
-第二种方法更普遍。利用了_类型推论_ -- 即编译器会根据传入的参数自动地帮助我们确定T的类型:
+第二种方法更普遍。利用了*类型推论* -- 即编译器会根据传入的参数自动地帮助我们确定 T 的类型:
```typescript
-let output = identity("myString"); // type of output will be 'string'
+let output = identity('myString'); // type of output will be 'string'
```
-注意我们没必要使用尖括号(`<>`)来明确地传入类型;编译器可以查看`myString`的值,然后把`T`设置为它的类型。 类型推论帮助我们保持代码精简和高可读性。如果编译器不能够自动地推断出类型的话,只能像上面那样明确的传入T的类型,在一些复杂的情况下,这是可能出现的。
+注意我们没必要使用尖括号(`<>`)来明确地传入类型;编译器可以查看`myString`的值,然后把`T`设置为它的类型。 类型推论帮助我们保持代码精简和高可读性。如果编译器不能够自动地推断出类型的话,只能像上面那样明确的传入 T 的类型,在一些复杂的情况下,这是可能出现的。
## 使用泛型变量
@@ -64,7 +66,7 @@ let output = identity("myString"); // type of output will be 'string'
```typescript
function identity(arg: T): T {
- return arg;
+ return arg;
}
```
@@ -72,8 +74,8 @@ function identity(arg: T): T {
```typescript
function loggingIdentity(arg: T): T {
- console.log(arg.length); // Error: T doesn't have .length
- return arg;
+ console.log(arg.length); // Error: T doesn't have .length
+ return arg;
}
```
@@ -83,19 +85,19 @@ function loggingIdentity(arg: T): T {
```typescript
function loggingIdentity(arg: T[]): T[] {
- console.log(arg.length); // Array has a .length, so no more error
- return arg;
+ console.log(arg.length); // Array has a .length, so no more error
+ return arg;
}
```
-你可以这样理解`loggingIdentity`的类型:泛型函数`loggingIdentity`,接收类型参数`T`和参数`arg`,它是个元素类型是`T`的数组,并返回元素类型是`T`的数组。 如果我们传入数字数组,将返回一个数字数组,因为此时`T`的的类型为`number`。 这可以让我们把泛型变量T当做类型的一部分使用,而不是整个类型,增加了灵活性。
+你可以这样理解`loggingIdentity`的类型:泛型函数`loggingIdentity`,接收类型参数`T`和参数`arg`,它是个元素类型是`T`的数组,并返回元素类型是`T`的数组。 如果我们传入数字数组,将返回一个数字数组,因为此时`T`的的类型为`number`。 这可以让我们把泛型变量 T 当做类型的一部分使用,而不是整个类型,增加了灵活性。
我们也可以这样实现上面的例子:
```typescript
function loggingIdentity(arg: Array): Array {
- console.log(arg.length); // Array has a .length, so no more error
- return arg;
+ console.log(arg.length); // Array has a .length, so no more error
+ return arg;
}
```
@@ -103,13 +105,13 @@ function loggingIdentity(arg: Array): Array {
## 泛型类型
-上一节,我们创建了identity通用函数,可以适用于不同的类型。 在这节,我们研究一下函数本身的类型,以及如何创建泛型接口。
+上一节,我们创建了 identity 通用函数,可以适用于不同的类型。 在这节,我们研究一下函数本身的类型,以及如何创建泛型接口。
泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样:
```typescript
function identity(arg: T): T {
- return arg;
+ return arg;
}
let myIdentity: (arg: T) => T = identity;
@@ -119,7 +121,7 @@ let myIdentity: (arg: T) => T = identity;
```typescript
function identity(arg: T): T {
- return arg;
+ return arg;
}
let myIdentity: (arg: U) => U = identity;
@@ -129,21 +131,21 @@ let myIdentity: (arg: U) => U = identity;
```typescript
function identity(arg: T): T {
- return arg;
+ return arg;
}
-let myIdentity: {(arg: T): T} = identity;
+let myIdentity: { (arg: T): T } = identity;
```
这引导我们去写第一个泛型接口了。 我们把上面例子里的对象字面量拿出来做为一个接口:
```typescript
interface GenericIdentityFn {
- (arg: T): T;
+ (arg: T): T;
}
function identity(arg: T): T {
- return arg;
+ return arg;
}
let myIdentity: GenericIdentityFn = identity;
@@ -153,11 +155,11 @@ let myIdentity: GenericIdentityFn = identity;
```typescript
interface GenericIdentityFn {
- (arg: T): T;
+ (arg: T): T;
}
function identity(arg: T): T {
- return arg;
+ return arg;
}
let myIdentity: GenericIdentityFn = identity;
@@ -173,23 +175,27 @@ let myIdentity: GenericIdentityFn = identity;
```typescript
class GenericNumber {
- zeroValue: T;
- add: (x: T, y: T) => T;
+ zeroValue: T;
+ add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber();
myGenericNumber.zeroValue = 0;
-myGenericNumber.add = function(x, y) { return x + y; };
+myGenericNumber.add = function (x, y) {
+ return x + y;
+};
```
`GenericNumber`类的使用是十分直观的,并且你可能已经注意到了,没有什么去限制它只能使用`number`类型。 也可以使用字符串或其它更复杂的类型。
```typescript
let stringNumeric = new GenericNumber();
-stringNumeric.zeroValue = "";
-stringNumeric.add = function(x, y) { return x + y; };
+stringNumeric.zeroValue = '';
+stringNumeric.add = function (x, y) {
+ return x + y;
+};
-console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
+console.log(stringNumeric.add(stringNumeric.zeroValue, 'test'));
```
与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。
@@ -202,36 +208,36 @@ console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
```typescript
function loggingIdentity(arg: T): T {
- console.log(arg.length); // Error: T doesn't have .length
- return arg;
+ console.log(arg.length); // Error: T doesn't have .length
+ return arg;
}
```
-相比于操作any所有类型,我们想要限制函数去处理任意带有`.length`属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。
+相比于操作 any 所有类型,我们想要限制函数去处理任意带有`.length`属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于 T 的约束要求。
为此,我们定义一个接口来描述约束条件。 创建一个包含`.length`属性的接口,使用这个接口和`extends`关键字来实现约束:
```typescript
interface Lengthwise {
- length: number;
+ length: number;
}
function loggingIdentity(arg: T): T {
- console.log(arg.length); // Now we know it has a .length property, so no more error
- return arg;
+ console.log(arg.length); // Now we know it has a .length property, so no more error
+ return arg;
}
```
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
```typescript
-loggingIdentity(3); // Error, number doesn't have a .length property
+loggingIdentity(3); // Error, number doesn't have a .length property
```
我们需要传入符合约束类型的值,必须包含必须的属性:
```typescript
-loggingIdentity({length: 10, value: 3});
+loggingIdentity({ length: 10, value: 3 });
```
### 在泛型约束中使用类型参数
@@ -240,22 +246,22 @@ loggingIdentity({length: 10, value: 3});
```typescript
function getProperty(obj: T, key: K) {
- return obj[key];
+ return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
-getProperty(x, "a"); // okay
-getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
+getProperty(x, 'a'); // okay
+getProperty(x, 'm'); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
```
### 在泛型里使用类类型
-在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型。比如,
+在 TypeScript 使用泛型创建工厂函数时,需要引用构造函数的类类型。比如,
```typescript
-function create(c: {new(): T; }): T {
- return new c();
+function create(c: { new (): T }): T {
+ return new c();
}
```
@@ -263,30 +269,29 @@ function create(c: {new(): T; }): T {
```typescript
class BeeKeeper {
- hasMask: boolean;
+ hasMask: boolean;
}
class ZooKeeper {
- nametag: string;
+ nametag: string;
}
class Animal {
- numLegs: number;
+ numLegs: number;
}
class Bee extends Animal {
- keeper: BeeKeeper;
+ keeper: BeeKeeper;
}
class Lion extends Animal {
- keeper: ZooKeeper;
+ keeper: ZooKeeper;
}
function createInstance(c: new () => A): A {
- return new c();
+ return new c();
}
-createInstance(Lion).keeper.nametag; // typechecks!
-createInstance(Bee).keeper.hasMask; // typechecks!
+createInstance(Lion).keeper.nametag; // typechecks!
+createInstance(Bee).keeper.hasMask; // typechecks!
```
-
diff --git a/zh/handbook/interfaces.md b/zh/handbook/interfaces.md
index d012cc10..963b417e 100644
--- a/zh/handbook/interfaces.md
+++ b/zh/handbook/interfaces.md
@@ -2,7 +2,7 @@
## 介绍
-TypeScript 的核心原则之一是对值所具有的_结构_进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
+TypeScript 的核心原则之一是对值所具有的*结构*进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在 TypeScript 里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
## 接口初探
@@ -13,7 +13,7 @@ function printLabel(labeledObj: { label: string }) {
console.log(labeledObj.label);
}
-let myObj = { size: 10, label: "Size 10 Object" };
+let myObj = { size: 10, label: 'Size 10 Object' };
printLabel(myObj);
```
@@ -30,7 +30,7 @@ function printLabel(labeledObj: LabeledValue) {
console.log(labeledObj.label);
}
-let myObj = { size: 10, label: "Size 10 Object" };
+let myObj = { size: 10, label: 'Size 10 Object' };
printLabel(myObj);
```
@@ -51,7 +51,7 @@ interface SquareConfig {
}
function createSquare(config: SquareConfig): { color: string; area: number } {
- let newSquare = { color: "white", area: 100 };
+ let newSquare = { color: 'white', area: 100 };
if (config.color) {
newSquare.color = config.color;
}
@@ -61,7 +61,7 @@ function createSquare(config: SquareConfig): { color: string; area: number } {
return newSquare;
}
-let mySquare = createSquare({ color: "black" });
+let mySquare = createSquare({ color: 'black' });
```
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个`?`符号。
@@ -75,7 +75,7 @@ interface SquareConfig {
}
function createSquare(config: SquareConfig): { color: string; area: number } {
- let newSquare = { color: "white", area: 100 };
+ let newSquare = { color: 'white', area: 100 };
if (config.clor) {
// Error: Property 'clor' does not exist on type 'SquareConfig'
newSquare.color = config.clor;
@@ -86,7 +86,7 @@ function createSquare(config: SquareConfig): { color: string; area: number } {
return newSquare;
}
-let mySquare = createSquare({ color: "black" });
+let mySquare = createSquare({ color: 'black' });
```
## 只读属性
@@ -144,18 +144,18 @@ function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
-let mySquare = createSquare({ colour: "red", width: 100 });
+let mySquare = createSquare({ colour: 'red', width: 100 });
```
注意传入`createSquare`的参数拼写为`colour`而不是`color`。 在 JavaScript 里,这会默默地失败。
你可能会争辩这个程序已经正确地类型化了,因为`width`属性是兼容的,不存在`color`属性,而且额外的`colour`属性是无意义的。
-然而,TypeScript 会认为这段代码可能存在 bug。 对象字面量会被特殊对待而且会经过_额外属性检查_,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。
+然而,TypeScript 会认为这段代码可能存在 bug。 对象字面量会被特殊对待而且会经过*额外属性检查*,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。
```typescript
// error: Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
-let mySquare = createSquare({ colour: "red", width: 100 });
+let mySquare = createSquare({ colour: 'red', width: 100 });
```
绕开这些检查非常简单。 最简便的方法是使用类型断言:
@@ -164,7 +164,7 @@ let mySquare = createSquare({ colour: "red", width: 100 });
let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
```
-然而,最佳的方式是能够添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性。 如果`SquareConfig`带有上面定义的类型的`color`和`width`属性,并且_还会_带有任意数量的其它属性,那么我们可以这样定义它:
+然而,最佳的方式是能够添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性。 如果`SquareConfig`带有上面定义的类型的`color`和`width`属性,并且*还会*带有任意数量的其它属性,那么我们可以这样定义它:
```typescript
interface SquareConfig {
@@ -179,14 +179,14 @@ interface SquareConfig {
还有最后一种跳过这些检查的方式,这可能会让你感到惊讶,它就是将这个对象赋值给一个另一个变量: 因为`squareOptions`不会经过额外属性检查,所以编译器不会报错。
```typescript
-let squareOptions = { colour: "red", width: 100 };
+let squareOptions = { colour: 'red', width: 100 };
let mySquare = createSquare(squareOptions);
```
上面的方法只在`squareOptions`和`SquareConfig`之间有共同的属性时才好用。 在这个例子中,这个属性为`width`。如果变量间不存在共同的对象属性将会报错。例如:
```typescript
-let squareOptions = { colour: "red" };
+let squareOptions = { colour: 'red' };
let mySquare = createSquare(squareOptions);
```
@@ -208,7 +208,7 @@ interface SearchFunc {
```typescript
let mySearch: SearchFunc;
-mySearch = function(source: string, subString: string) {
+mySearch = function (source: string, subString: string) {
let result = source.search(subString);
return result > -1;
};
@@ -218,7 +218,7 @@ mySearch = function(source: string, subString: string) {
```typescript
let mySearch: SearchFunc;
-mySearch = function(src: string, sub: string): boolean {
+mySearch = function (src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
};
@@ -228,7 +228,7 @@ mySearch = function(src: string, sub: string): boolean {
```typescript
let mySearch: SearchFunc;
-mySearch = function(src, sub) {
+mySearch = function (src, sub) {
let result = src.search(sub);
return result > -1;
};
@@ -241,15 +241,15 @@ let mySearch: SearchFunc;
// error: Type '(src: string, sub: string) => string' is not assignable to type 'SearchFunc'.
// Type 'string' is not assignable to type 'boolean'.
-mySearch = function(src, sub) {
+mySearch = function (src, sub) {
let result = src.search(sub);
- return "string";
+ return 'string';
};
```
## 可索引的类型
-与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如`a[10]`或`ageMap["daniel"]`。 可索引类型具有一个_索引签名_,它描述了对象索引的类型,还有相应的索引返回值类型。 让我们看一个例子:
+与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如`a[10]`或`ageMap["daniel"]`。 可索引类型具有一个*索引签名*,它描述了对象索引的类型,还有相应的索引返回值类型。 让我们看一个例子:
```typescript
interface StringArray {
@@ -257,7 +257,7 @@ interface StringArray {
}
let myArray: StringArray;
-myArray = ["Bob", "Fred"];
+myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0];
```
@@ -295,9 +295,9 @@ interface NumberDictionary {
```typescript
interface NumberOrStringDictionary {
- [index: string]: number | string;
- length: number; // ok, length is a number
- name: string; // ok, name is a string
+ [index: string]: number | string;
+ length: number; // ok, length is a number
+ name: string; // ok, name is a string
}
```
@@ -307,8 +307,8 @@ interface NumberOrStringDictionary {
interface ReadonlyStringArray {
readonly [index: number]: string;
}
-let myArray: ReadonlyStringArray = ["Alice", "Bob"];
-myArray[2] = "Mallory"; // error!
+let myArray: ReadonlyStringArray = ['Alice', 'Bob'];
+myArray[2] = 'Mallory'; // error!
```
你不能设置`myArray[2]`,因为索引签名是只读的。
@@ -387,13 +387,13 @@ function createClock(
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
- console.log("beep beep");
+ console.log('beep beep');
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
- console.log("tick tock");
+ console.log('tick tock');
}
}
@@ -417,7 +417,7 @@ interface ClockInterface {
const Clock: ClockConstructor = class Clock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
- console.log("beep beep");
+ console.log('beep beep');
}
};
```
@@ -436,7 +436,7 @@ interface Square extends Shape {
}
let square = {} as Square;
-square.color = "blue";
+square.color = 'blue';
square.sideLength = 10;
```
@@ -456,7 +456,7 @@ interface Square extends Shape, PenStroke {
}
let square = {} as Square;
-square.color = "blue";
+square.color = 'blue';
square.sideLength = 10;
square.penWidth = 5.0;
```
@@ -475,9 +475,9 @@ interface Counter {
}
function getCounter(): Counter {
- let counter = function(start: number) {} as Counter;
+ let counter = function (start: number) {} as Counter;
counter.interval = 123;
- counter.reset = function() {};
+ counter.reset = function () {};
return counter;
}
@@ -513,8 +513,8 @@ class TextBox extends Control {
}
class ImageControl implements SelectableControl {
-// Error: Class 'ImageControl' incorrectly implements interface 'SelectableControl'.
-// Types have separate declarations of a private property 'state'.
+ // Error: Class 'ImageControl' incorrectly implements interface 'SelectableControl'.
+ // Types have separate declarations of a private property 'state'.
private state: any;
select() {}
}
@@ -523,4 +523,3 @@ class ImageControl implements SelectableControl {
在上面的例子里,`SelectableControl`包含了`Control`的所有成员,包括私有成员`state`。 因为`state`是私有成员,所以只能够是`Control`的子类们才能实现`SelectableControl`接口。 因为只有`Control`的子类才能够拥有一个声明于`Control`的私有成员`state`,这对私有成员的兼容性是必需的。
在`Control`类内部,是允许通过`SelectableControl`的实例来访问私有成员`state`的。 实际上,`SelectableControl`就像`Control`一样,并拥有一个`select`方法。 `Button`和`TextBox`类是`SelectableControl`的子类(因为它们都继承自`Control`并有`select`方法)。而对于 `ImageControl` 类,它有自身的私有成员 `state` 而不是通过继承 `Control` 得来的,所以它不可以实现 `SelectableControl` 。
-
diff --git a/zh/handbook/literal-types.md b/zh/handbook/literal-types.md
index d3e27d1c..5d757b8e 100644
--- a/zh/handbook/literal-types.md
+++ b/zh/handbook/literal-types.md
@@ -109,4 +109,3 @@ type ValidationResult =
| ValidationSuccess
| ValidationFailure;
```
-
diff --git a/zh/javascript/type-checking-javascript-files.md b/zh/javascript/type-checking-javascript-files.md
index f713e256..5a61e9aa 100644
--- a/zh/javascript/type-checking-javascript-files.md
+++ b/zh/javascript/type-checking-javascript-files.md
@@ -785,4 +785,3 @@ var normal;
```
不同于JSDoc类型系统,TypeScript只允许将类型标记为包不包含`null`。 没有明确的`Non-nullable` -- 如果启用了`strictNullChecks`,那么`number`是非`null`的。 如果没有启用,那么`number`是可以为`null`的。
-
diff --git a/zh/project-config/README.md b/zh/project-config/README.md
index e4791e83..e9903534 100644
--- a/zh/project-config/README.md
+++ b/zh/project-config/README.md
@@ -1,10 +1,10 @@
# 工程配置
- * [tsconfig.json](project-config/tsconfig.json.md)
- * [工程引用](project-config/project-references.md)
- * [NPM包的类型](project-config/typings-for-npm-packages.md)
- * [编译选项](project-config/compiler-options.md)
- * [配置 Watch](project-config/configuring-watch.md)
- * [在MSBuild里使用编译选项](project-config/compiler-options-in-msbuild.md)
- * [与其它构建工具整合](project-config/integrating-with-build-tools.md)
- * [使用TypeScript的每日构建版本](project-config/nightly-builds.md)
\ No newline at end of file
+- [tsconfig.json](project-config/tsconfig.json.md)
+- [工程引用](project-config/project-references.md)
+- [NPM 包的类型](project-config/typings-for-npm-packages.md)
+- [编译选项](project-config/compiler-options.md)
+- [配置 Watch](project-config/configuring-watch.md)
+- [在 MSBuild 里使用编译选项](project-config/compiler-options-in-msbuild.md)
+- [与其它构建工具整合](project-config/integrating-with-build-tools.md)
+- [使用 TypeScript 的每日构建版本](project-config/nightly-builds.md)
diff --git a/zh/project-config/compiler-options-in-msbuild.md b/zh/project-config/compiler-options-in-msbuild.md
index d27b537d..7ad7914f 100644
--- a/zh/project-config/compiler-options-in-msbuild.md
+++ b/zh/project-config/compiler-options-in-msbuild.md
@@ -114,4 +114,3 @@
## TypeScriptCompileBlocked
如果你使用其它的构建工具(比如,gulp, grunt等等)并且使用VS做为开发和调试工具,那么在工程里设置`true`。 这样VS只会提供给你编辑的功能,而不会在你按F5的时候去构建。
-
diff --git a/zh/project-config/compiler-options.md b/zh/project-config/compiler-options.md
index 7ce5cc3b..f7ffb5e7 100644
--- a/zh/project-config/compiler-options.md
+++ b/zh/project-config/compiler-options.md
@@ -94,4 +94,3 @@
* 在[`tsconfig.json`](tsconfig.json.md)文件里设置编译器选项。
* 在[MSBuild工程](compiler-options-in-msbuild.md)里设置编译器选项。
-
diff --git a/zh/project-config/configuring-watch.md b/zh/project-config/configuring-watch.md
index 2a5bd4e3..4797994a 100644
--- a/zh/project-config/configuring-watch.md
+++ b/zh/project-config/configuring-watch.md
@@ -30,4 +30,3 @@
`fs.watch`使用文件系统事件通知文件及目录的变化。 但是它依赖于操作系统,且事件通知并不完全可靠,在很多操作系统上的行为难以预料。 还可能会有创建监视个数的限制,如Linux系统,在包含大量文件的程序中监视器个数很快被耗尽。 但也正是因为它使用文件系统事件,不需要占用过多的CPU周期。 典型地,编译器使用`fs.watch`来监视目录(比如配置文件里声明的源码目录,无法进行模块解析的目录)。 这样就可以处理改动通知不准确的问题。 但递归地监视仅在Windows和OSX系统上支持。 这就意味着在其它系统上要使用替代方案。
`fs.watchFile`使用轮询,因此涉及到CPU周期。 但是这是最可靠的获取文件/目录状态的机制。 典型地,编译器使用`fs.watchFile`监视源文件,配置文件和消失的文件(失去文件引用),这意味着对CPU的使用依赖于程序里文件的数量。
-
diff --git a/zh/project-config/integrating-with-build-tools.md b/zh/project-config/integrating-with-build-tools.md
index 16ce1cfa..3e493fad 100644
--- a/zh/project-config/integrating-with-build-tools.md
+++ b/zh/project-config/integrating-with-build-tools.md
@@ -274,4 +274,3 @@ module.exports = {
* 安装完成后,Rebuild。
更多详细信息请参考[Package Manager Dialog](http://docs.nuget.org/Consume/Package-Manager-Dialog)和[using nightly builds with NuGet](https://github.com/Microsoft/TypeScript/wiki/Nightly-drops#using-nuget-with-msbuild)
-
diff --git a/zh/project-config/project-references.md b/zh/project-config/project-references.md
index c6ce0386..c44408b8 100644
--- a/zh/project-config/project-references.md
+++ b/zh/project-config/project-references.md
@@ -182,4 +182,3 @@ B C
### `outFile`的结构
使用了`outFile`的编译输出结构十分灵活,因为相对路径是无关紧要的。 要注意的是,你通常不需要使用`prepend` - 因为这会改善构建时间并结省I/O。 TypeScript项目本身是一个好的参照 - 我们有一些“library”的工程和一些“endpoint”工程,“endpoint”工程会确保足够小并仅仅导入它们需要的“library”。
-
diff --git a/zh/project-config/tsconfig.json.md b/zh/project-config/tsconfig.json.md
index e6ef0a94..e8329933 100644
--- a/zh/project-config/tsconfig.json.md
+++ b/zh/project-config/tsconfig.json.md
@@ -188,4 +188,3 @@
## 模式
到这里查看模式: [http://json.schemastore.org/tsconfig](http://json.schemastore.org/tsconfig).
-
diff --git a/zh/reference/advanced-types.md b/zh/reference/advanced-types.md
index 1d48f3fa..79ff227a 100644
--- a/zh/reference/advanced-types.md
+++ b/zh/reference/advanced-types.md
@@ -4,36 +4,36 @@
交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如,`Person & Serializable & Loggable`同时是`Person`_和_`Serializable`_和_`Loggable`。 就是说这个类型的对象同时拥有了这三种类型的成员。
-我们大多是在混入(mixins)或其它不适合典型面向对象模型的地方看到交叉类型的使用。 (在JavaScript里发生这种情况的场合很多!) 下面是如何创建混入的一个简单例子\("target": "es5"\):
+我们大多是在混入(mixins)或其它不适合典型面向对象模型的地方看到交叉类型的使用。 (在 JavaScript 里发生这种情况的场合很多!) 下面是如何创建混入的一个简单例子\("target": "es5"\):
```typescript
function extend(first: First, second: Second): First & Second {
- const result: Partial = {};
- for (const prop in first) {
- if (first.hasOwnProperty(prop)) {
- (result as First)[prop] = first[prop];
- }
+ const result: Partial = {};
+ for (const prop in first) {
+ if (first.hasOwnProperty(prop)) {
+ (result as First)[prop] = first[prop];
}
- for (const prop in second) {
- if (second.hasOwnProperty(prop)) {
- (result as Second)[prop] = second[prop];
- }
+ }
+ for (const prop in second) {
+ if (second.hasOwnProperty(prop)) {
+ (result as Second)[prop] = second[prop];
}
- return result as First & Second;
+ }
+ return result as First & Second;
}
class Person {
- constructor(public name: string) { }
+ constructor(public name: string) {}
}
interface Loggable {
- log(name: string): void;
+ log(name: string): void;
}
class ConsoleLogger implements Loggable {
- log(name) {
- console.log(`Hello, I'm ${name}.`);
- }
+ log(name) {
+ console.log(`Hello, I'm ${name}.`);
+ }
}
const jim = extend(new Person('Jim'), ConsoleLogger.prototype);
@@ -51,27 +51,27 @@ jim.log(jim.name);
* If 'padding' is a number, then that number of spaces is added to the left side.
*/
function padLeft(value: string, padding: any) {
- if (typeof padding === "number") {
- return Array(padding + 1).join(" ") + value;
- }
- if (typeof padding === "string") {
- return padding + value;
- }
- throw new Error(`Expected string or number, got '${padding}'.`);
+ if (typeof padding === 'number') {
+ return Array(padding + 1).join(' ') + value;
+ }
+ if (typeof padding === 'string') {
+ return padding + value;
+ }
+ throw new Error(`Expected string or number, got '${padding}'.`);
}
-padLeft("Hello world", 4); // returns " Hello world"
+padLeft('Hello world', 4); // returns " Hello world"
```
-`padLeft`存在一个问题,`padding`参数的类型指定成了`any`。 这就是说我们可以传入一个既不是`number`也不是`string`类型的参数,但是TypeScript却不报错。
+`padLeft`存在一个问题,`padding`参数的类型指定成了`any`。 这就是说我们可以传入一个既不是`number`也不是`string`类型的参数,但是 TypeScript 却不报错。
```typescript
-let indentedString = padLeft("Hello world", true); // 编译阶段通过,运行时报错
+let indentedString = padLeft('Hello world', true); // 编译阶段通过,运行时报错
```
在传统的面向对象语言里,我们可能会将这两种类型抽象成有层级的类型。 这么做显然是非常清晰的,但同时也存在了过度设计。 `padLeft`原始版本的好处之一是允许我们传入原始类型。 这样做的话使用起来既简单又方便。 如果我们就是想使用已经存在的函数的话,这种新的方式就不适用了。
-代替`any`, 我们可以使用_联合类型_做为`padding`的参数:
+代替`any`, 我们可以使用*联合类型*做为`padding`的参数:
```typescript
/**
@@ -80,10 +80,10 @@ let indentedString = padLeft("Hello world", true); // 编译阶段通过,运
* If 'padding' is a number, then that number of spaces is added to the left side.
*/
function padLeft(value: string, padding: string | number) {
- // ...
+ // ...
}
-let indentedString = padLeft("Hello world", true); // errors during compilation
+let indentedString = padLeft('Hello world', true); // errors during compilation
```
联合类型表示一个值可以是几种类型之一。 我们用竖线(`|`)分隔每个类型,所以`number | string | boolean`表示一个值可以是`number`,`string`,或`boolean`。
@@ -92,39 +92,38 @@ let indentedString = padLeft("Hello world", true); // errors during compilation
```typescript
interface Bird {
- fly();
- layEggs();
+ fly();
+ layEggs();
}
interface Fish {
- swim();
- layEggs();
+ swim();
+ layEggs();
}
function getSmallPet(): Fish | Bird {
- // ...
+ // ...
}
let pet = getSmallPet();
pet.layEggs(); // okay
-pet.swim(); // errors
+pet.swim(); // errors
```
-这里的联合类型可能有点复杂,但是你很容易就习惯了。 如果一个值的类型是`A | B`,我们能够_确定_的是它包含了`A`_和_`B`中共有的成员。 这个例子里,`Bird`具有一个`fly`成员。 我们不能确定一个`Bird | Fish`类型的变量是否有`fly`方法。 如果变量在运行时是`Fish`类型,那么调用`pet.fly()`就出错了。
+这里的联合类型可能有点复杂,但是你很容易就习惯了。 如果一个值的类型是`A | B`,我们能够*确定*的是它包含了`A`_和_`B`中共有的成员。 这个例子里,`Bird`具有一个`fly`成员。 我们不能确定一个`Bird | Fish`类型的变量是否有`fly`方法。 如果变量在运行时是`Fish`类型,那么调用`pet.fly()`就出错了。
## 类型守卫与类型区分(Type Guards and Differentiating Types)
-联合类型适合于那些值可以为不同类型的情况。 但当我们想确切地了解是否为`Fish`时怎么办? JavaScript里常用来区分2个可能值的方法是检查成员是否存在。 如之前提及的,我们只能访问联合类型中共同拥有的成员。
+联合类型适合于那些值可以为不同类型的情况。 但当我们想确切地了解是否为`Fish`时怎么办? JavaScript 里常用来区分 2 个可能值的方法是检查成员是否存在。 如之前提及的,我们只能访问联合类型中共同拥有的成员。
```typescript
let pet = getSmallPet();
// 每一个成员访问都会报错
if (pet.swim) {
- pet.swim();
-}
-else if (pet.fly) {
- pet.fly();
+ pet.swim();
+} else if (pet.fly) {
+ pet.fly();
}
```
@@ -134,9 +133,9 @@ else if (pet.fly) {
let pet = getSmallPet();
if ((pet as Fish).swim) {
- (pet as Fish).swim();
+ (pet as Fish).swim();
} else if ((pet as Bird).fly) {
- (pet as Bird).fly();
+ (pet as Bird).fly();
}
```
@@ -144,34 +143,33 @@ if ((pet as Fish).swim) {
这里可以注意到我们不得不多次使用类型断言。 假若我们一旦检查过类型,就能在之后的每个分支里清楚地知道`pet`的类型的话就好了。
-TypeScript里的_类型守卫_机制让它成为了现实。 类型守卫就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。
+TypeScript 里的*类型守卫*机制让它成为了现实。 类型守卫就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。
#### 使用类型判定
-要定义一个类型守卫,我们只要简单地定义一个函数,它的返回值是一个_类型谓词_:
+要定义一个类型守卫,我们只要简单地定义一个函数,它的返回值是一个*类型谓词*:
```typescript
function isFish(pet: Fish | Bird): pet is Fish {
- return (pet as Fish).swim !== undefined;
+ return (pet as Fish).swim !== undefined;
}
```
在这个例子里,`pet is Fish`就是类型谓词。 谓词为`parameterName is Type`这种形式,`parameterName`必须是来自于当前函数签名里的一个参数名。
-每当使用一些变量调用`isFish`时,TypeScript会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。
+每当使用一些变量调用`isFish`时,TypeScript 会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。
```typescript
// 'swim' 和 'fly' 调用都没有问题了
if (isFish(pet)) {
- pet.swim();
-}
-else {
- pet.fly();
+ pet.swim();
+} else {
+ pet.fly();
}
```
-注意TypeScript不仅知道在`if`分支里`pet`是`Fish`类型; 它还清楚在`else`分支里,一定_不是_`Fish`类型,一定是`Bird`类型。
+注意 TypeScript 不仅知道在`if`分支里`pet`是`Fish`类型; 它还清楚在`else`分支里,一定*不是*`Fish`类型,一定是`Bird`类型。
#### 使用`in`操作符
@@ -181,10 +179,10 @@ else {
```typescript
function move(pet: Fish | Bird) {
- if ("swim" in pet) {
- return pet.swim();
- }
- return pet.fly();
+ if ('swim' in pet) {
+ return pet.swim();
+ }
+ return pet.fly();
}
```
@@ -194,83 +192,83 @@ function move(pet: Fish | Bird) {
```typescript
function isNumber(x: any): x is number {
- return typeof x === "number";
+ return typeof x === 'number';
}
function isString(x: any): x is string {
- return typeof x === "string";
+ return typeof x === 'string';
}
function padLeft(value: string, padding: string | number) {
- if (isNumber(padding)) {
- return Array(padding + 1).join(" ") + value;
- }
- if (isString(padding)) {
- return padding + value;
- }
- throw new Error(`Expected string or number, got '${padding}'.`);
+ if (isNumber(padding)) {
+ return Array(padding + 1).join(' ') + value;
+ }
+ if (isString(padding)) {
+ return padding + value;
+ }
+ throw new Error(`Expected string or number, got '${padding}'.`);
}
```
-然而,必须要定义一个函数来判断类型是否是原始类型,这太痛苦了。 幸运的是,现在我们不必将`typeof x === "number"`抽象成一个函数,因为TypeScript可以将它识别为一个类型守卫。 也就是说我们可以直接在代码里检查类型了。
+然而,必须要定义一个函数来判断类型是否是原始类型,这太痛苦了。 幸运的是,现在我们不必将`typeof x === "number"`抽象成一个函数,因为 TypeScript 可以将它识别为一个类型守卫。 也就是说我们可以直接在代码里检查类型了。
```typescript
function padLeft(value: string, padding: string | number) {
- if (typeof padding === "number") {
- return Array(padding + 1).join(" ") + value;
- }
- if (typeof padding === "string") {
- return padding + value;
- }
- throw new Error(`Expected string or number, got '${padding}'.`);
+ if (typeof padding === 'number') {
+ return Array(padding + 1).join(' ') + value;
+ }
+ if (typeof padding === 'string') {
+ return padding + value;
+ }
+ throw new Error(`Expected string or number, got '${padding}'.`);
}
```
-这些_`typeof`类型守卫_只有两种形式能被识别:`typeof v === "typename"`和`typeof v !== "typename"`,`"typename"`必须是`"number"`,`"string"`,`"boolean"`或`"symbol"`。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型守卫。
+这些*`typeof`类型守卫*只有两种形式能被识别:`typeof v === "typename"`和`typeof v !== "typename"`,`"typename"`必须是`"number"`,`"string"`,`"boolean"`或`"symbol"`。 但是 TypeScript 并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型守卫。
### `instanceof`类型守卫
-如果你已经阅读了`typeof`类型守卫并且对JavaScript里的`instanceof`操作符熟悉的话,你可能已经猜到了这节要讲的内容。
+如果你已经阅读了`typeof`类型守卫并且对 JavaScript 里的`instanceof`操作符熟悉的话,你可能已经猜到了这节要讲的内容。
-_`instanceof`类型守卫_是通过构造函数来细化类型的一种方式。 比如,我们借鉴一下之前字符串填充的例子:
+*`instanceof`类型守卫*是通过构造函数来细化类型的一种方式。 比如,我们借鉴一下之前字符串填充的例子:
```typescript
interface Padder {
- getPaddingString(): string
+ getPaddingString(): string;
}
class SpaceRepeatingPadder implements Padder {
- constructor(private numSpaces: number) { }
- getPaddingString() {
- return Array(this.numSpaces + 1).join(" ");
- }
+ constructor(private numSpaces: number) {}
+ getPaddingString() {
+ return Array(this.numSpaces + 1).join(' ');
+ }
}
class StringPadder implements Padder {
- constructor(private value: string) { }
- getPaddingString() {
- return this.value;
- }
+ constructor(private value: string) {}
+ getPaddingString() {
+ return this.value;
+ }
}
function getRandomPadder() {
- return Math.random() < 0.5 ?
- new SpaceRepeatingPadder(4) :
- new StringPadder(" ");
+ return Math.random() < 0.5
+ ? new SpaceRepeatingPadder(4)
+ : new StringPadder(' ');
}
// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();
if (padder instanceof SpaceRepeatingPadder) {
- padder; // 类型细化为'SpaceRepeatingPadder'
+ padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
- padder; // 类型细化为'StringPadder'
+ padder; // 类型细化为'StringPadder'
}
```
-`instanceof`的右侧要求是一个构造函数,TypeScript将细化为:
+`instanceof`的右侧要求是一个构造函数,TypeScript 将细化为:
1. 此构造函数的`prototype`属性的类型,如果它的类型不为`any`的话
2. 构造签名所返回的类型的联合
@@ -279,20 +277,20 @@ if (padder instanceof StringPadder) {
## 可以为`null`的类型
-TypeScript具有两种特殊的类型,`null`和`undefined`,它们分别具有值`null`和`undefined`. 我们在[基础类型](basic-types.md)一节里已经做过简要说明。 默认情况下,类型检查器认为`null`与`undefined`可以赋值给任何类型。 `null`与`undefined`是所有其它类型的一个有效值。 这也意味着,你阻止不了将它们赋值给其它类型,就算是你想要阻止这种情况也不行。 `null`的发明者,Tony Hoare,称它为[价值亿万美金的错误](https://en.wikipedia.org/wiki/Null_pointer#History)。
+TypeScript 具有两种特殊的类型,`null`和`undefined`,它们分别具有值`null`和`undefined`. 我们在[基础类型](basic-types.md)一节里已经做过简要说明。 默认情况下,类型检查器认为`null`与`undefined`可以赋值给任何类型。 `null`与`undefined`是所有其它类型的一个有效值。 这也意味着,你阻止不了将它们赋值给其它类型,就算是你想要阻止这种情况也不行。 `null`的发明者,Tony Hoare,称它为[价值亿万美金的错误](https://en.wikipedia.org/wiki/Null_pointer#History)。
`--strictNullChecks`标记可以解决此错误:当你声明一个变量时,它不会自动地包含`null`或`undefined`。 你可以使用联合类型明确的包含它们:
```typescript
-let s = "foo";
+let s = 'foo';
s = null; // 错误, 'null'不能赋值给'string'
-let sn: string | null = "bar";
+let sn: string | null = 'bar';
sn = null; // 可以
sn = undefined; // error, 'undefined'不能赋值给'string | null'
```
-注意,按照JavaScript的语义,TypeScript会把`null`和`undefined`区别对待。 `string | null`,`string | undefined`和`string | undefined | null`是不同的类型。
+注意,按照 JavaScript 的语义,TypeScript 会把`null`和`undefined`区别对待。 `string | null`,`string | undefined`和`string | undefined | null`是不同的类型。
### 可选参数和可选属性
@@ -300,7 +298,7 @@ sn = undefined; // error, 'undefined'不能赋值给'string | null'
```typescript
function f(x: number, y?: number) {
- return x + (y || 0);
+ return x + (y || 0);
}
f(1, 2);
f(1);
@@ -312,8 +310,8 @@ f(1, null); // error, 'null' is not assignable to 'number | undefined'
```typescript
class C {
- a: number;
- b?: number;
+ a: number;
+ b?: number;
}
let c = new C();
c.a = 12;
@@ -325,16 +323,15 @@ c.b = null; // error, 'null' is not assignable to 'number | undefined'
### 类型守卫和类型断言
-由于可以为`null`的类型是通过联合类型实现,那么你需要使用类型守卫来去除`null`。 幸运地是这与在JavaScript里写的代码一致:
+由于可以为`null`的类型是通过联合类型实现,那么你需要使用类型守卫来去除`null`。 幸运地是这与在 JavaScript 里写的代码一致:
```typescript
function f(sn: string | null): string {
- if (sn == null) {
- return "default";
- }
- else {
- return sn;
- }
+ if (sn == null) {
+ return 'default';
+ } else {
+ return sn;
+ }
}
```
@@ -342,7 +339,7 @@ function f(sn: string | null): string {
```typescript
function f(sn: string | null): string {
- return sn || "default";
+ return sn || 'default';
}
```
@@ -353,16 +350,16 @@ function broken(name: string | null): string {
function postfix(epithet: string) {
return name.charAt(0) + '. the ' + epithet; // error, 'name' is possibly null
}
- name = name || "Bob";
- return postfix("great");
+ name = name || 'Bob';
+ return postfix('great');
}
function fixed(name: string | null): string {
function postfix(epithet: string) {
return name!.charAt(0) + '. the ' + epithet; // ok
}
- name = name || "Bob";
- return postfix("great");
+ name = name || 'Bob';
+ return postfix('great');
}
```
@@ -377,16 +374,15 @@ type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
- if (typeof n === 'string') {
- return n;
- }
- else {
- return n();
- }
+ if (typeof n === 'string') {
+ return n;
+ } else {
+ return n();
+ }
}
```
-起别名不会新建一个类型 - 它创建了一个新_名字_来引用那个类型。 给原始类型起别名通常没什么用,尽管可以做为文档的一种形式使用。
+起别名不会新建一个类型 - 它创建了一个新*名字*来引用那个类型。 给原始类型起别名通常没什么用,尽管可以做为文档的一种形式使用。
同接口一样,类型别名也可以是泛型 - 我们可以添加类型参数并且在别名声明的右侧传入:
@@ -398,10 +394,10 @@ type Container = { value: T };
```typescript
type Tree = {
- value: T;
- left: Tree;
- right: Tree;
-}
+ value: T;
+ left: Tree;
+ right: Tree;
+};
```
与交叉类型一起使用,我们可以创建出一些十分稀奇古怪的类型。
@@ -410,7 +406,7 @@ type Tree = {
type LinkedList = T & { next: LinkedList };
interface Person {
- name: string;
+ name: string;
}
var people: LinkedList;
@@ -433,15 +429,15 @@ type Yikes = Array; // error
其一,接口创建了一个新的名字,可以在其它任何地方使用。 类型别名并不创建新名字—比如,错误信息就不会使用别名。 在下面的示例代码里,在编译器中将鼠标悬停在`interfaced`上,显示它返回的是`Interface`,但悬停在`aliased`上时,显示的却是对象字面量类型。
```typescript
-type Alias = { num: number }
+type Alias = { num: number };
interface Interface {
- num: number;
+ num: number;
}
declare function aliased(arg: Alias): Alias;
declare function interfaced(arg: Interface): Interface;
```
-在旧版本的TypeScript里,类型别名不能被继承和实现(它们也不能继承和实现其它类型)。从TypeScript 2.7开始,类型别名可以被继承并生成新的交叉类型。例如:`type Cat = Animal & { purrs: true }`。
+在旧版本的 TypeScript 里,类型别名不能被继承和实现(它们也不能继承和实现其它类型)。从 TypeScript 2.7 开始,类型别名可以被继承并生成新的交叉类型。例如:`type Cat = Animal & { purrs: true }`。
因为[软件中的对象应该对于扩展是开放的,但是对于修改是封闭的](https://en.wikipedia.org/wiki/Open/closed_principle),你应该尽量去使用接口代替类型别名。
@@ -452,25 +448,22 @@ declare function interfaced(arg: Interface): Interface;
字符串字面量类型允许你指定字符串必须的固定值。 在实际应用中,字符串字面量类型可以与联合类型,类型守卫和类型别名很好的配合。 通过结合使用这些特性,你可以实现类似枚举类型的字符串。
```typescript
-type Easing = "ease-in" | "ease-out" | "ease-in-out";
+type Easing = 'ease-in' | 'ease-out' | 'ease-in-out';
class UIElement {
- animate(dx: number, dy: number, easing: Easing) {
- if (easing === "ease-in") {
- // ...
- }
- else if (easing === "ease-out") {
- }
- else if (easing === "ease-in-out") {
- }
- else {
- // error! should not pass null or undefined.
- }
+ animate(dx: number, dy: number, easing: Easing) {
+ if (easing === 'ease-in') {
+ // ...
+ } else if (easing === 'ease-out') {
+ } else if (easing === 'ease-in-out') {
+ } else {
+ // error! should not pass null or undefined.
}
+ }
}
let button = new UIElement();
-button.animate(0, 0, "ease-in");
-button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here
+button.animate(0, 0, 'ease-in');
+button.animate(0, 0, 'uneasy'); // error: "uneasy" is not allowed here
```
你只能从三种允许的字符中选择其一来做为参数传递,传入其它值则会产生错误。
@@ -482,32 +475,32 @@ Argument of type '"uneasy"' is not assignable to parameter of type '"ease-in" |
字符串字面量类型还可以用于区分函数重载:
```typescript
-function createElement(tagName: "img"): HTMLImageElement;
-function createElement(tagName: "input"): HTMLInputElement;
+function createElement(tagName: 'img'): HTMLImageElement;
+function createElement(tagName: 'input'): HTMLInputElement;
// ... more overloads ...
function createElement(tagName: string): Element {
- // ... code goes here ...
+ // ... code goes here ...
}
```
## 数字字面量类型
-TypeScript还具有数字字面量类型。
+TypeScript 还具有数字字面量类型。
```typescript
function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
- // ...
+ // ...
}
```
-我们很少直接这样使用,但它们可以用在缩小范围调试bug的时候:
+我们很少直接这样使用,但它们可以用在缩小范围调试 bug 的时候:
```typescript
function foo(x: number) {
- if (x !== 1 || x !== 2) {
- // ~~~~~~~
- // Operator '!==' cannot be applied to types '1' and '2'.
- }
+ if (x !== 1 || x !== 2) {
+ // ~~~~~~~
+ // Operator '!==' cannot be applied to types '1' and '2'.
+ }
}
```
@@ -521,7 +514,7 @@ function foo(x: number) {
## 可辨识联合(Discriminated Unions)
-你可以合并单例类型,联合类型,类型守卫和类型别名来创建一个叫做_可辨识联合_的高级模式,它也称做_标签联合_或_代数数据类型_。 可辨识联合在函数式编程里很有用处。 一些语言会自动地为你辨识联合;而TypeScript则基于已有的JavaScript模式。 它具有3个要素:
+你可以合并单例类型,联合类型,类型守卫和类型别名来创建一个叫做*可辨识联合*的高级模式,它也称做*标签联合*或*代数数据类型*。 可辨识联合在函数式编程里很有用处。 一些语言会自动地为你辨识联合;而 TypeScript 则基于已有的 JavaScript 模式。 它具有 3 个要素:
1. 具有普通的单例类型属性—_可辨识的特征_。
2. 一个类型别名包含了那些类型的联合—_联合_。
@@ -529,21 +522,21 @@ function foo(x: number) {
```typescript
interface Square {
- kind: "square";
- size: number;
+ kind: 'square';
+ size: number;
}
interface Rectangle {
- kind: "rectangle";
- width: number;
- height: number;
+ kind: 'rectangle';
+ width: number;
+ height: number;
}
interface Circle {
- kind: "circle";
- radius: number;
+ kind: 'circle';
+ radius: number;
}
```
-首先我们声明了将要联合的接口。 每个接口都有`kind`属性但有不同的字符串字面量类型。 `kind`属性称做_可辨识的特征_或_标签_。 其它的属性则特定于各个接口。 注意,目前各个接口间是没有联系的。 下面我们把它们联合到一起:
+首先我们声明了将要联合的接口。 每个接口都有`kind`属性但有不同的字符串字面量类型。 `kind`属性称做*可辨识的特征*或*标签*。 其它的属性则特定于各个接口。 注意,目前各个接口间是没有联系的。 下面我们把它们联合到一起:
```typescript
type Shape = Square | Rectangle | Circle;
@@ -553,11 +546,14 @@ type Shape = Square | Rectangle | Circle;
```typescript
function area(s: Shape) {
- switch (s.kind) {
- case "square": return s.size * s.size;
- case "rectangle": return s.height * s.width;
- case "circle": return Math.PI * s.radius ** 2;
- }
+ switch (s.kind) {
+ case 'square':
+ return s.size * s.size;
+ case 'rectangle':
+ return s.height * s.width;
+ case 'circle':
+ return Math.PI * s.radius ** 2;
+ }
}
```
@@ -568,108 +564,112 @@ function area(s: Shape) {
```typescript
type Shape = Square | Rectangle | Circle | Triangle;
function area(s: Shape) {
- switch (s.kind) {
- case "square": return s.size * s.size;
- case "rectangle": return s.height * s.width;
- case "circle": return Math.PI * s.radius ** 2;
- }
- // should error here - we didn't handle case "triangle"
+ switch (s.kind) {
+ case 'square':
+ return s.size * s.size;
+ case 'rectangle':
+ return s.height * s.width;
+ case 'circle':
+ return Math.PI * s.radius ** 2;
+ }
+ // should error here - we didn't handle case "triangle"
}
```
有两种方式可以实现。 首先是启用`--strictNullChecks`并且指定一个返回值类型:
```typescript
-function area(s: Shape): number { // error: returns number | undefined
- switch (s.kind) {
- case "square": return s.size * s.size;
- case "rectangle": return s.height * s.width;
- case "circle": return Math.PI * s.radius ** 2;
- }
+function area(s: Shape): number {
+ // error: returns number | undefined
+ switch (s.kind) {
+ case 'square':
+ return s.size * s.size;
+ case 'rectangle':
+ return s.height * s.width;
+ case 'circle':
+ return Math.PI * s.radius ** 2;
+ }
}
```
-因为`switch`没有包含所有情况,所以TypeScript认为这个函数有时候会返回`undefined`。 如果你明确地指定了返回值类型为`number`,那么你会看到一个错误,因为实际上返回值的类型为`number | undefined`。 然而,这种方法存在些微妙之处且`--strictNullChecks`对旧代码支持不好。
+因为`switch`没有包含所有情况,所以 TypeScript 认为这个函数有时候会返回`undefined`。 如果你明确地指定了返回值类型为`number`,那么你会看到一个错误,因为实际上返回值的类型为`number | undefined`。 然而,这种方法存在些微妙之处且`--strictNullChecks`对旧代码支持不好。
第二种方法使用`never`类型,编译器用它来进行完整性检查:
```typescript
function assertNever(x: never): never {
- throw new Error("Unexpected object: " + x);
+ throw new Error('Unexpected object: ' + x);
}
function area(s: Shape) {
- switch (s.kind) {
- case "square": return s.size * s.size;
- case "rectangle": return s.height * s.width;
- case "circle": return Math.PI * s.radius ** 2;
- default: return assertNever(s); // error here if there are missing cases
- }
+ switch (s.kind) {
+ case 'square':
+ return s.size * s.size;
+ case 'rectangle':
+ return s.height * s.width;
+ case 'circle':
+ return Math.PI * s.radius ** 2;
+ default:
+ return assertNever(s); // error here if there are missing cases
+ }
}
```
-这里,`assertNever`检查`s`是否为`never`类型—即为除去所有可能情况后剩下的类型。 如果你忘记了某个case,那么`s`将具有一个真实的类型并且你会得到一个错误。 这种方式需要你定义一个额外的函数,但是在你忘记某个case的时候也更加明显。
+这里,`assertNever`检查`s`是否为`never`类型—即为除去所有可能情况后剩下的类型。 如果你忘记了某个 case,那么`s`将具有一个真实的类型并且你会得到一个错误。 这种方式需要你定义一个额外的函数,但是在你忘记某个 case 的时候也更加明显。
## 多态的`this`类型
-多态的`this`类型表示的是某个包含类或接口的_子类型_。 这被称做_F_-bounded多态性。 它能很容易的表现连贯接口间的继承,比如。 在计算器的例子里,在每个操作之后都返回`this`类型:
+多态的`this`类型表示的是某个包含类或接口的*子类型*。 这被称做*F*-bounded 多态性。 它能很容易的表现连贯接口间的继承,比如。 在计算器的例子里,在每个操作之后都返回`this`类型:
```typescript
class BasicCalculator {
- public constructor(protected value: number = 0) { }
- public currentValue(): number {
- return this.value;
- }
- public add(operand: number): this {
- this.value += operand;
- return this;
- }
- public multiply(operand: number): this {
- this.value *= operand;
- return this;
- }
- // ... other operations go here ...
+ public constructor(protected value: number = 0) {}
+ public currentValue(): number {
+ return this.value;
+ }
+ public add(operand: number): this {
+ this.value += operand;
+ return this;
+ }
+ public multiply(operand: number): this {
+ this.value *= operand;
+ return this;
+ }
+ // ... other operations go here ...
}
-let v = new BasicCalculator(2)
- .multiply(5)
- .add(1)
- .currentValue();
+let v = new BasicCalculator(2).multiply(5).add(1).currentValue();
```
由于这个类使用了`this`类型,你可以继承它,新的类可以直接使用之前的方法,不需要做任何的改变。
```typescript
class ScientificCalculator extends BasicCalculator {
- public constructor(value = 0) {
- super(value);
- }
- public sin() {
- this.value = Math.sin(this.value);
- return this;
- }
- // ... other operations go here ...
+ public constructor(value = 0) {
+ super(value);
+ }
+ public sin() {
+ this.value = Math.sin(this.value);
+ return this;
+ }
+ // ... other operations go here ...
}
-let v = new ScientificCalculator(2)
- .multiply(5)
- .sin()
- .add(1)
- .currentValue();
+let v = new ScientificCalculator(2).multiply(5).sin().add(1).currentValue();
```
如果没有`this`类型,`ScientificCalculator`就不能够在继承`BasicCalculator`的同时还保持接口的连贯性。 `multiply`将会返回`BasicCalculator`,它并没有`sin`方法。 然而,使用`this`类型,`multiply`会返回`this`,在这里就是`ScientificCalculator`。
## 索引类型(Index types)
-使用索引类型,编译器就能够检查使用了动态属性名的代码。 例如,一个常见的JavaScript模式是从对象中选取属性的子集。
+使用索引类型,编译器就能够检查使用了动态属性名的代码。 例如,一个常见的 JavaScript 模式是从对象中选取属性的子集。
```javascript
function pluck(o, propertyNames) {
- return propertyNames.map(n => o[n]);
+ return propertyNames.map(n => o[n]);
}
```
-下面是如何在TypeScript里使用此函数,通过**索引类型查询**和**索引访问**操作符:
+下面是如何在 TypeScript 里使用此函数,通过**索引类型查询**和**索引访问**操作符:
```typescript
function pluck(o: T, propertyNames: K[]): T[K][] {
@@ -677,14 +677,14 @@ function pluck(o: T, propertyNames: K[]): T[K][] {
}
interface Car {
- manufacturer: string;
- model: string;
- year: number;
+ manufacturer: string;
+ model: string;
+ year: number;
}
let taxi: Car = {
- manufacturer: 'Toyota',
- model: 'Camry',
- year: 2014
+ manufacturer: 'Toyota',
+ model: 'Camry',
+ year: 2014,
};
// Manufacturer and model are both of type string,
@@ -693,7 +693,7 @@ let makeAndModel: string[] = pluck(taxi, ['manufacturer', 'model']);
// If we try to pluck model and year, we get an
// array of a union type: (string | number)[]
-let modelYear = pluck(taxi, ['model', 'year'])
+let modelYear = pluck(taxi, ['model', 'year']);
```
编译器会检查`manufacturer`和`model`是否真的是`Car`上的一个属性。 本例还引入了几个新的类型操作符。 首先是`keyof T`,**索引类型查询操作符**。 对于任何类型`T`,`keyof T`的结果为`T`上已知的公共属性名的联合。 例如:
@@ -713,7 +713,7 @@ pluck(taxi, ['year', 'unknown']);
```typescript
function getProperty(o: T, propertyName: K): T[K] {
- return o[propertyName]; // o[propertyName] is of type T[K]
+ return o[propertyName]; // o[propertyName] is of type T[K]
}
```
@@ -729,11 +729,11 @@ let unknown = getProperty(taxi, 'unknown');
### 索引类型和字符串索引签名
-`keyof`和`T[K]`与字符串索引签名进行交互。索引签名的参数类型必须为`number`或`string`。 如果你有一个带有字符串索引签名的类型,那么`keyof T`会是`string | number`。 \(并非只有`string`,因为在JavaScript里,你可以使用字符串`object['42']`或 数字`object[42]`索引来访问对象属性\)。 并且`T[string]`为索引签名的类型:
+`keyof`和`T[K]`与字符串索引签名进行交互。索引签名的参数类型必须为`number`或`string`。 如果你有一个带有字符串索引签名的类型,那么`keyof T`会是`string | number`。 \(并非只有`string`,因为在 JavaScript 里,你可以使用字符串`object['42']`或 数字`object[42]`索引来访问对象属性\)。 并且`T[string]`为索引签名的类型:
```typescript
interface Dictionary {
- [key: string]: T;
+ [key: string]: T;
}
let keys: keyof Dictionary; // string | number
let value: Dictionary['foo']; // number
@@ -743,7 +743,7 @@ let value: Dictionary['foo']; // number
```typescript
interface Dictionary {
- [key: number]: T;
+ [key: number]: T;
}
let keys: keyof Dictionary; // number
let value: Dictionary['foo']; // Error, Property 'foo' does not exist on type 'Dictionary'.
@@ -756,8 +756,8 @@ let value: Dictionary[42]; // number
```typescript
interface PersonPartial {
- name?: string;
- age?: number;
+ name?: string;
+ age?: number;
}
```
@@ -765,20 +765,20 @@ interface PersonPartial {
```typescript
interface PersonReadonly {
- readonly name: string;
- readonly age: number;
+ readonly name: string;
+ readonly age: number;
}
```
-这在JavaScript里经常出现,TypeScript提供了从旧类型中创建新类型的一种方式 — **映射类型**。 在映射类型里,新类型以相同的形式去转换旧类型里每个属性。 例如,你可以令每个属性成为`readonly`类型或可选的。 下面是一些例子:
+这在 JavaScript 里经常出现,TypeScript 提供了从旧类型中创建新类型的一种方式 — **映射类型**。 在映射类型里,新类型以相同的形式去转换旧类型里每个属性。 例如,你可以令每个属性成为`readonly`类型或可选的。 下面是一些例子:
```typescript
type Readonly = {
- readonly [P in keyof T]: T[P];
-}
+ readonly [P in keyof T]: T[P];
+};
type Partial = {
- [P in keyof T]?: T[P];
-}
+ [P in keyof T]?: T[P];
+};
```
像下面这样使用:
@@ -794,13 +794,12 @@ type ReadonlyPerson = Readonly;
// 这样使用
type PartialWithNewMember = {
[P in keyof T]?: T[P];
-} & { newMember: boolean }
+} & { newMember: boolean };
// 不要这样使用
// 这会报错!
type PartialWithNewMember = {
[P in keyof T]?: T[P];
- newMember: boolean;
-}
+};
```
下面来看看最简单的映射类型和它的组成部分:
@@ -820,23 +819,23 @@ type Flags = { [K in Keys]: boolean };
```typescript
type Flags = {
- option1: boolean;
- option2: boolean;
-}
+ option1: boolean;
+ option2: boolean;
+};
```
在真正的应用里,可能不同于上面的`Readonly`或`Partial`。 它们会基于一些已存在的类型,且按照一定的方式转换字段。 这就是`keyof`和索引访问类型要做的事情:
```typescript
-type NullablePerson = { [P in keyof Person]: Person[P] | null }
-type PartialPerson = { [P in keyof Person]?: Person[P] }
+type NullablePerson = { [P in keyof Person]: Person[P] | null };
+type PartialPerson = { [P in keyof Person]?: Person[P] };
```
但它更有用的地方是可以有一些通用版本。
```typescript
-type Nullable = { [P in keyof T]: T[P] | null }
-type Partial = { [P in keyof T]?: T[P] }
+type Nullable = { [P in keyof T]: T[P] | null };
+type Partial = { [P in keyof T]?: T[P] };
```
在这些例子里,属性列表是`keyof T`且结果类型是`T[P]`的变体。 这是使用通用映射类型的一个好模版。 因为这类转换是[同态](https://en.wikipedia.org/wiki/Homomorphism)的,映射只作用于`T`的属性而没有其它的。 编译器知道在添加任何新属性之前可以拷贝所有存在的属性修饰符。 例如,假设`Person.name`是只读的,那么`Partial.name`也将是只读的且为可选的。
@@ -845,33 +844,33 @@ type Partial = { [P in keyof T]?: T[P] }
```typescript
type Proxy = {
- get(): T;
- set(value: T): void;
-}
+ get(): T;
+ set(value: T): void;
+};
type Proxify = {
- [P in keyof T]: Proxy;
-}
+ [P in keyof T]: Proxy;
+};
function proxify(o: T): Proxify {
- // ... wrap proxies ...
+ // ... wrap proxies ...
}
let proxyProps = proxify(props);
```
-注意`Readonly`和`Partial`用处不小,因此它们与`Pick`和`Record`一同被包含进了TypeScript的标准库里:
+注意`Readonly`和`Partial`用处不小,因此它们与`Pick`和`Record`一同被包含进了 TypeScript 的标准库里:
```typescript
type Pick = {
- [P in K]: T[P];
-}
+ [P in K]: T[P];
+};
type Record = {
- [P in K]: T;
-}
+ [P in K]: T;
+};
```
`Readonly`,`Partial`和`Pick`是同态的,但`Record`不是。 因为`Record`并不需要输入类型来拷贝属性,所以它不属于同态:
```typescript
-type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
+type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>;
```
非同态类型本质上会创建新的属性,因此它们不会从它处拷贝属性修饰符。
@@ -882,11 +881,11 @@ type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
```typescript
function unproxify(t: Proxify): T {
- let result = {} as T;
- for (const k in t) {
- result[k] = t[k].get();
- }
- return result;
+ let result = {} as T;
+ for (const k in t) {
+ result[k] = t[k].get();
+ }
+ return result;
}
let originalProps = unproxify(proxyProps);
@@ -896,7 +895,7 @@ let originalProps = unproxify(proxyProps);
### 有条件类型
-TypeScript 2.8引入了_有条件类型_,它能够表示非统一的类型。 有条件的类型会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一:
+TypeScript 2.8 引入了*有条件类型*,它能够表示非统一的类型。 有条件的类型会以一个条件表达式进行类型关系检测,从而在两种类型中选择其一:
```typescript
T extends U ? X : Y
@@ -904,7 +903,7 @@ T extends U ? X : Y
上面的类型意思是,若`T`能够赋值给`U`,那么类型是`X`,否则为`Y`。
-有条件的类型`T extends U ? X : Y`或者_解析_为`X`,或者_解析_为`Y`,再或者_延迟_解析,因为它可能依赖一个或多个类型变量。 若`T`或`U`包含类型参数,那么是否解析为`X`或`Y`或推迟,取决于类型系统是否有足够的信息来确定`T`总是可以赋值给`U`。
+有条件的类型`T extends U ? X : Y`或者*解析*为`X`,或者*解析*为`Y`,再或者*延迟*解析,因为它可能依赖一个或多个类型变量。 若`T`或`U`包含类型参数,那么是否解析为`X`或`Y`或推迟,取决于类型系统是否有足够的信息来确定`T`总是可以赋值给`U`。
下面是一些类型可以被立即解析的例子:
@@ -912,47 +911,51 @@ T extends U ? X : Y
declare function f(x: T): T extends true ? string : number;
// Type is 'string | number
-let x = f(Math.random() < 0.5)
+let x = f(Math.random() < 0.5);
```
另外一个例子涉及`TypeName`类型别名,它使用了嵌套了有条件类型:
```typescript
-type TypeName =
- T extends string ? "string" :
- T extends number ? "number" :
- T extends boolean ? "boolean" :
- T extends undefined ? "undefined" :
- T extends Function ? "function" :
- "object";
+type TypeName = T extends string
+ ? 'string'
+ : T extends number
+ ? 'number'
+ : T extends boolean
+ ? 'boolean'
+ : T extends undefined
+ ? 'undefined'
+ : T extends Function
+ ? 'function'
+ : 'object';
-type T0 = TypeName; // "string"
-type T1 = TypeName<"a">; // "string"
-type T2 = TypeName; // "boolean"
-type T3 = TypeName<() => void>; // "function"
-type T4 = TypeName; // "object"
+type T0 = TypeName; // "string"
+type T1 = TypeName<'a'>; // "string"
+type T2 = TypeName; // "boolean"
+type T3 = TypeName<() => void>; // "function"
+type T4 = TypeName; // "object"
```
下面是一个有条件类型被推迟解析的例子:
```typescript
interface Foo {
- propA: boolean;
- propB: boolean;
+ propA: boolean;
+ propB: boolean;
}
declare function f(x: T): T extends Foo ? string : number;
function foo(x: U) {
- // Has type 'U extends Foo ? string : number'
- let a = f(x);
+ // Has type 'U extends Foo ? string : number'
+ let a = f(x);
- // This assignment is allowed though!
- let b: string | number = a;
+ // This assignment is allowed though!
+ let b: string | number = a;
}
```
-这里,`a`变量含有未确定的有条件类型。 当有另一段代码调用`foo`,它会用其它类型替换`U`,TypeScript将重新计算有条件类型,决定它是否可以选择一个分支。
+这里,`a`变量含有未确定的有条件类型。 当有另一段代码调用`foo`,它会用其它类型替换`U`,TypeScript 将重新计算有条件类型,决定它是否可以选择一个分支。
与此同时,我们可以将有条件类型赋值给其它类型,只要有条件类型的每个分支都可以赋值给目标类型。 因此在我们的例子里,我们可以将`U extends Foo ? string : number`赋值给`string | number`,因为不管这个有条件类型最终结果是什么,它只能是`string`或`number`。
@@ -963,9 +966,9 @@ function foo(x: U) {
**例子**
```typescript
-type T10 = TypeName void)>; // "string" | "function"
-type T12 = TypeName; // "string" | "object" | "undefined"
-type T11 = TypeName; // "object"
+type T10 = TypeName void)>; // "string" | "function"
+type T12 = TypeName; // "string" | "object" | "undefined"
+type T11 = TypeName; // "object"
```
在`T extends U ? X : Y`的实例化里,对`T`的引用被解析为联合类型的一部分(比如,`T`指向某一单个部分,在有条件类型分布到联合类型之后)。 此外,在`X`内对`T`的引用有一个附加的类型参数约束`U`(例如,`T`被当成在`X`内可赋值给`U`)。
@@ -977,62 +980,66 @@ type BoxedValue = { value: T };
type BoxedArray = { array: T[] };
type Boxed = T extends any[] ? BoxedArray : BoxedValue;
-type T20 = Boxed; // BoxedValue;
-type T21 = Boxed; // BoxedArray;
-type T22 = Boxed; // BoxedValue | BoxedArray;
+type T20 = Boxed; // BoxedValue;
+type T21 = Boxed; // BoxedArray;
+type T22 = Boxed; // BoxedValue | BoxedArray;
```
注意在`Boxed`的`true`分支里,`T`有个额外的约束`any[]`,因此它适用于`T[number]`数组元素类型。同时也注意一下有条件类型是如何分布成联合类型的。
-有条件类型的分布式的属性可以方便地用来_过滤_联合类型:
+有条件类型的分布式的属性可以方便地用来*过滤*联合类型:
```typescript
-type Diff = T extends U ? never : T; // Remove types from T that are assignable to U
-type Filter = T extends U ? T : never; // Remove types from T that are not assignable to U
+type Diff = T extends U ? never : T; // Remove types from T that are assignable to U
+type Filter = T extends U ? T : never; // Remove types from T that are not assignable to U
-type T30 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
-type T31 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
-type T32 = Diff void), Function>; // string | number
-type T33 = Filter void), Function>; // () => void
+type T30 = Diff<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'>; // "b" | "d"
+type T31 = Filter<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'>; // "a" | "c"
+type T32 = Diff void), Function>; // string | number
+type T33 = Filter void), Function>; // () => void
-type NonNullable = Diff; // Remove null and undefined from T
+type NonNullable = Diff; // Remove null and undefined from T
-type T34 = NonNullable; // string | number
-type T35 = NonNullable; // string | string[]
+type T34 = NonNullable; // string | number
+type T35 = NonNullable; // string | string[]
function f1(x: T, y: NonNullable) {
- x = y; // Ok
- y = x; // Error
+ x = y; // Ok
+ y = x; // Error
}
function f2(x: T, y: NonNullable) {
- x = y; // Ok
- y = x; // Error
- let s1: string = x; // Error
- let s2: string = y; // Ok
+ x = y; // Ok
+ y = x; // Error
+ let s1: string = x; // Error
+ let s2: string = y; // Ok
}
```
有条件类型与映射类型结合时特别有用:
```typescript
-type FunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T];
+type FunctionPropertyNames = {
+ [K in keyof T]: T[K] extends Function ? K : never;
+}[keyof T];
type FunctionProperties = Pick>;
-type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
+type NonFunctionPropertyNames = {
+ [K in keyof T]: T[K] extends Function ? never : K;
+}[keyof T];
type NonFunctionProperties = Pick>;
interface Part {
- id: number;
- name: string;
- subparts: Part[];
- updatePart(newName: string): void;
+ id: number;
+ name: string;
+ subparts: Part[];
+ updatePart(newName: string): void;
}
-type T40 = FunctionPropertyNames; // "updatePart"
-type T41 = NonFunctionPropertyNames; // "id" | "name" | "subparts"
-type T42 = FunctionProperties; // { updatePart(newName: string): void }
-type T43 = NonFunctionProperties; // { id: number, name: string, subparts: Part[] }
+type T40 = FunctionPropertyNames; // "updatePart"
+type T41 = NonFunctionPropertyNames; // "id" | "name" | "subparts"
+type T42 = FunctionProperties; // { updatePart(newName: string): void }
+type T43 = NonFunctionProperties; // { id: number, name: string, subparts: Part[] }
```
与联合类型和交叉类型相似,有条件类型不允许递归地引用自己。比如下面的错误。
@@ -1047,7 +1054,7 @@ type ElementType = T extends any[] ? ElementType : T;
#### 有条件类型中的类型推断
-现在在有条件类型的`extends`子语句中,允许出现`infer`声明,它会引入一个待推断的类型变量。 这个推断的类型变量可以在有条件类型的true分支中被引用。 允许出现多个同类型变量的`infer`。
+现在在有条件类型的`extends`子语句中,允许出现`infer`声明,它会引入一个待推断的类型变量。 这个推断的类型变量可以在有条件类型的 true 分支中被引用。 允许出现多个同类型变量的`infer`。
例如,下面代码会提取函数类型的返回值类型:
@@ -1058,105 +1065,110 @@ type ReturnType = T extends (...args: any[]) => infer R ? R : any;
有条件类型可以嵌套来构成一系列的匹配模式,按顺序进行求值:
```typescript
-type Unpacked =
- T extends (infer U)[] ? U :
- T extends (...args: any[]) => infer U ? U :
- T extends Promise ? U :
- T;
+type Unpacked = T extends (infer U)[]
+ ? U
+ : T extends (...args: any[]) => infer U
+ ? U
+ : T extends Promise
+ ? U
+ : T;
-type T0 = Unpacked; // string
-type T1 = Unpacked; // string
-type T2 = Unpacked<() => string>; // string
-type T3 = Unpacked>; // string
-type T4 = Unpacked[]>; // Promise
-type T5 = Unpacked[]>>; // string
+type T0 = Unpacked; // string
+type T1 = Unpacked; // string
+type T2 = Unpacked<() => string>; // string
+type T3 = Unpacked>; // string
+type T4 = Unpacked[]>; // Promise
+type T5 = Unpacked[]>>; // string
```
下面的例子解释了在协变位置上,同一个类型变量的多个候选类型会被推断为联合类型:
```typescript
-type Foo = T extends { a: infer U, b: infer U } ? U : never;
-type T10 = Foo<{ a: string, b: string }>; // string
-type T11 = Foo<{ a: string, b: number }>; // string | number
+type Foo = T extends { a: infer U; b: infer U } ? U : never;
+type T10 = Foo<{ a: string; b: string }>; // string
+type T11 = Foo<{ a: string; b: number }>; // string | number
```
相似地,在抗变位置上,同一个类型变量的多个候选类型会被推断为交叉类型:
```typescript
-type Bar = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
-type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>; // string
-type T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>; // string & number
+type Bar = T extends { a: (x: infer U) => void; b: (x: infer U) => void }
+ ? U
+ : never;
+type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
+type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // string & number
```
-当推断具有多个调用签名(例如函数重载类型)的类型时,用_最后_的签名(大概是最自由的包含所有情况的签名)进行推断。 无法根据参数类型列表来解析重载。
+当推断具有多个调用签名(例如函数重载类型)的类型时,用*最后*的签名(大概是最自由的包含所有情况的签名)进行推断。 无法根据参数类型列表来解析重载。
```typescript
declare function foo(x: string): number;
declare function foo(x: number): string;
declare function foo(x: string | number): string | number;
-type T30 = ReturnType; // string | number
+type T30 = ReturnType; // string | number
```
无法在正常类型参数的约束子语句中使用`infer`声明:
```typescript
-type ReturnType infer R> = R; // 错误,不支持
+type ReturnType infer R> = R; // 错误,不支持
```
但是,可以这样达到同样的效果,在约束里删掉类型变量,用有条件类型替换:
```typescript
type AnyFunction = (...args: any[]) => any;
-type ReturnType = T extends (...args: any[]) => infer R ? R : any;
+type ReturnType = T extends (...args: any[]) => infer R
+ ? R
+ : any;
```
#### 预定义的有条件类型
-TypeScript 2.8在`lib.d.ts`里增加了一些预定义的有条件类型:
+TypeScript 2.8 在`lib.d.ts`里增加了一些预定义的有条件类型:
-* `Exclude` -- 从`T`中剔除可以赋值给`U`的类型。
-* `Extract` -- 提取`T`中可以赋值给`U`的类型。
-* `NonNullable` -- 从`T`中剔除`null`和`undefined`。
-* `ReturnType` -- 获取函数返回值类型。
-* `InstanceType` -- 获取构造函数类型的实例类型。
+- `Exclude` -- 从`T`中剔除可以赋值给`U`的类型。
+- `Extract` -- 提取`T`中可以赋值给`U`的类型。
+- `NonNullable` -- 从`T`中剔除`null`和`undefined`。
+- `ReturnType` -- 获取函数返回值类型。
+- `InstanceType` -- 获取构造函数类型的实例类型。
**Example**
```typescript
-type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
-type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
+type T00 = Exclude<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'>; // "b" | "d"
+type T01 = Extract<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'>; // "a" | "c"
-type T02 = Exclude void), Function>; // string | number
-type T03 = Extract void), Function>; // () => void
+type T02 = Exclude void), Function>; // string | number
+type T03 = Extract void), Function>; // () => void
-type T04 = NonNullable; // string | number
-type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[]
+type T04 = NonNullable; // string | number
+type T05 = NonNullable<(() => string) | string[] | null | undefined>; // (() => string) | string[]
function f1(s: string) {
- return { a: 1, b: s };
+ return { a: 1, b: s };
}
class C {
- x = 0;
- y = 0;
+ x = 0;
+ y = 0;
}
-type T10 = ReturnType<() => string>; // string
-type T11 = ReturnType<(s: string) => void>; // void
-type T12 = ReturnType<(() => T)>; // {}
-type T13 = ReturnType<(() => T)>; // number[]
-type T14 = ReturnType; // { a: number, b: string }
-type T15 = ReturnType; // any
-type T16 = ReturnType; // never
-type T17 = ReturnType; // Error
-type T18 = ReturnType; // Error
+type T10 = ReturnType<() => string>; // string
+type T11 = ReturnType<(s: string) => void>; // void
+type T12 = ReturnType<() => T>; // {}
+type T13 = ReturnType<() => T>; // number[]
+type T14 = ReturnType; // { a: number, b: string }
+type T15 = ReturnType; // any
+type T16 = ReturnType; // never
+type T17 = ReturnType; // Error
+type T18 = ReturnType; // Error
-type T20 = InstanceType; // C
-type T21 = InstanceType; // any
-type T22 = InstanceType; // never
-type T23 = InstanceType; // Error
-type T24 = InstanceType; // Error
+type T20 = InstanceType; // C
+type T21 = InstanceType; // any
+type T22 = InstanceType; // never
+type T23 = InstanceType; // Error
+type T24 = InstanceType; // Error
```
> 注意:`Exclude`类型是[建议的](https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458)`Diff`类型的一种实现。我们使用`Exclude`这个名字是为了避免破坏已经定义了`Diff`的代码,并且我们感觉这个名字能更好地表达类型的语义。
-
diff --git a/zh/reference/declaration-merging.md b/zh/reference/declaration-merging.md
index 99b16c55..993d76ec 100644
--- a/zh/reference/declaration-merging.md
+++ b/zh/reference/declaration-merging.md
@@ -2,23 +2,23 @@
## 介绍
-TypeScript中有些独特的概念可以在类型层面上描述JavaScript对象的模型。 这其中尤其独特的一个例子是“声明合并”的概念。 理解了这个概念,将有助于操作现有的JavaScript代码。 同时,也会有助于理解更多高级抽象的概念。
+TypeScript 中有些独特的概念可以在类型层面上描述 JavaScript 对象的模型。 这其中尤其独特的一个例子是“声明合并”的概念。 理解了这个概念,将有助于操作现有的 JavaScript 代码。 同时,也会有助于理解更多高级抽象的概念。
对本文件来讲,“声明合并”是指编译器将针对同一个名字的两个独立声明合并为单一声明。 合并后的声明同时拥有原先两个声明的特性。 任何数量的声明都可被合并;不局限于两个声明。
## 基础概念
-TypeScript中的声明会创建以下三种实体之一:命名空间,类型或值。 创建命名空间的声明会新建一个命名空间,它包含了用(.)符号来访问时使用的名字。 创建类型的声明是:用声明的模型创建一个类型并绑定到给定的名字上。 最后,创建值的声明会创建在JavaScript输出中看到的值。
+TypeScript 中的声明会创建以下三种实体之一:命名空间,类型或值。 创建命名空间的声明会新建一个命名空间,它包含了用(.)符号来访问时使用的名字。 创建类型的声明是:用声明的模型创建一个类型并绑定到给定的名字上。 最后,创建值的声明会创建在 JavaScript 输出中看到的值。
| Declaration Type | Namespace | Type | Value |
-| :--- | :---: | :---: | :---: |
-| Namespace | X | | X |
-| Class | | X | X |
-| Enum | | X | X |
-| Interface | | X | |
-| Type Alias | | X | |
-| Function | | | X |
-| Variable | | | X |
+| :--------------- | :-------: | :--: | :---: |
+| Namespace | X | | X |
+| Class | | X | X |
+| Enum | | X | X |
+| Interface | | X | |
+| Type Alias | | X | |
+| Function | | | X |
+| Variable | | | X |
理解每个声明创建了什么,有助于理解当声明合并时有哪些东西被合并了。
@@ -28,15 +28,15 @@ TypeScript中的声明会创建以下三种实体之一:命名空间,类型
```typescript
interface Box {
- height: number;
- width: number;
+ height: number;
+ width: number;
}
interface Box {
- scale: number;
+ scale: number;
}
-let box: Box = {height: 5, width: 6, scale: 10};
+let box: Box = { height: 5, width: 6, scale: 10 };
```
接口的非函数的成员应该是唯一的。 如果它们不是唯一的,那么它们必须是相同的类型。 如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错。
@@ -47,16 +47,16 @@ let box: Box = {height: 5, width: 6, scale: 10};
```typescript
interface Cloner {
- clone(animal: Animal): Animal;
+ clone(animal: Animal): Animal;
}
interface Cloner {
- clone(animal: Sheep): Sheep;
+ clone(animal: Sheep): Sheep;
}
interface Cloner {
- clone(animal: Dog): Dog;
- clone(animal: Cat): Cat;
+ clone(animal: Dog): Dog;
+ clone(animal: Cat): Cat;
}
```
@@ -64,30 +64,30 @@ interface Cloner {
```typescript
interface Cloner {
- clone(animal: Dog): Dog;
- clone(animal: Cat): Cat;
- clone(animal: Sheep): Sheep;
- clone(animal: Animal): Animal;
+ clone(animal: Dog): Dog;
+ clone(animal: Cat): Cat;
+ clone(animal: Sheep): Sheep;
+ clone(animal: Animal): Animal;
}
```
注意每组接口里的声明顺序保持不变,但各组接口之间的顺序是后来的接口重载出现在靠前位置。
-这个规则有一个例外是当出现特殊的函数签名时。 如果签名里有一个参数的类型是_单一_的字符串字面量(比如,不是字符串字面量的联合类型),那么它将会被提升到重载列表的最顶端。
+这个规则有一个例外是当出现特殊的函数签名时。 如果签名里有一个参数的类型是*单一*的字符串字面量(比如,不是字符串字面量的联合类型),那么它将会被提升到重载列表的最顶端。
比如,下面的接口会合并到一起:
```typescript
interface Document {
- createElement(tagName: any): Element;
+ createElement(tagName: any): Element;
}
interface Document {
- createElement(tagName: "div"): HTMLDivElement;
- createElement(tagName: "span"): HTMLSpanElement;
+ createElement(tagName: 'div'): HTMLDivElement;
+ createElement(tagName: 'span'): HTMLSpanElement;
}
interface Document {
- createElement(tagName: string): HTMLElement;
- createElement(tagName: "canvas"): HTMLCanvasElement;
+ createElement(tagName: string): HTMLElement;
+ createElement(tagName: 'canvas'): HTMLCanvasElement;
}
```
@@ -95,11 +95,11 @@ interface Document {
```typescript
interface Document {
- createElement(tagName: "canvas"): HTMLCanvasElement;
- createElement(tagName: "div"): HTMLDivElement;
- createElement(tagName: "span"): HTMLSpanElement;
- createElement(tagName: string): HTMLElement;
- createElement(tagName: any): Element;
+ createElement(tagName: 'canvas'): HTMLCanvasElement;
+ createElement(tagName: 'div'): HTMLDivElement;
+ createElement(tagName: 'span'): HTMLSpanElement;
+ createElement(tagName: string): HTMLElement;
+ createElement(tagName: any): Element;
}
```
@@ -115,12 +115,14 @@ interface Document {
```typescript
namespace Animals {
- export class Zebra { }
+ export class Zebra {}
}
namespace Animals {
- export interface Legged { numberOfLegs: number; }
- export class Dog { }
+ export interface Legged {
+ numberOfLegs: number;
+ }
+ export class Dog {}
}
```
@@ -128,10 +130,12 @@ namespace Animals {
```typescript
namespace Animals {
- export interface Legged { numberOfLegs: number; }
+ export interface Legged {
+ numberOfLegs: number;
+ }
- export class Zebra { }
- export class Dog { }
+ export class Zebra {}
+ export class Dog {}
}
```
@@ -141,17 +145,17 @@ namespace Animals {
```typescript
namespace Animal {
- let haveMuscles = true;
+ let haveMuscles = true;
- export function animalsHaveMuscles() {
- return haveMuscles;
- }
+ export function animalsHaveMuscles() {
+ return haveMuscles;
+ }
}
namespace Animal {
- export function doAnimalsHaveMuscles() {
- return haveMuscles; // Error, because haveMuscles is not accessible here
- }
+ export function doAnimalsHaveMuscles() {
+ return haveMuscles; // Error, because haveMuscles is not accessible here
+ }
}
```
@@ -159,7 +163,7 @@ namespace Animal {
## 命名空间与类和函数和枚举类型合并
-命名空间可以与其它类型的声明进行合并。 只要命名空间的定义符合将要合并类型的定义。合并结果包含两者的声明类型。 TypeScript使用这个功能去实现一些JavaScript里的设计模式。
+命名空间可以与其它类型的声明进行合并。 只要命名空间的定义符合将要合并类型的定义。合并结果包含两者的声明类型。 TypeScript 使用这个功能去实现一些 JavaScript 里的设计模式。
### 合并命名空间和类
@@ -167,101 +171,97 @@ namespace Animal {
```typescript
class Album {
- label: Album.AlbumLabel;
+ label: Album.AlbumLabel;
}
namespace Album {
- export class AlbumLabel { }
+ export class AlbumLabel {}
}
```
合并规则与上面`合并命名空间`小节里讲的规则一致,我们必须导出`AlbumLabel`类,好让合并的类能访问。 合并结果是一个类并带有一个内部类。 你也可以使用命名空间为类增加一些静态属性。
-除了内部类的模式,你在JavaScript里,创建一个函数稍后扩展它增加一些属性也是很常见的。 TypeScript使用声明合并来达到这个目的并保证类型安全。
+除了内部类的模式,你在 JavaScript 里,创建一个函数稍后扩展它增加一些属性也是很常见的。 TypeScript 使用声明合并来达到这个目的并保证类型安全。
```typescript
function buildLabel(name: string): string {
- return buildLabel.prefix + name + buildLabel.suffix;
+ return buildLabel.prefix + name + buildLabel.suffix;
}
namespace buildLabel {
- export let suffix = "";
- export let prefix = "Hello, ";
+ export let suffix = '';
+ export let prefix = 'Hello, ';
}
-console.log(buildLabel("Sam Smith"));
+console.log(buildLabel('Sam Smith'));
```
相似的,命名空间可以用来扩展枚举型:
```typescript
enum Color {
- red = 1,
- green = 2,
- blue = 4
+ red = 1,
+ green = 2,
+ blue = 4,
}
namespace Color {
- export function mixColor(colorName: string) {
- if (colorName == "yellow") {
- return Color.red + Color.green;
- }
- else if (colorName == "white") {
- return Color.red + Color.green + Color.blue;
- }
- else if (colorName == "magenta") {
- return Color.red + Color.blue;
- }
- else if (colorName == "cyan") {
- return Color.green + Color.blue;
- }
+ export function mixColor(colorName: string) {
+ if (colorName == 'yellow') {
+ return Color.red + Color.green;
+ } else if (colorName == 'white') {
+ return Color.red + Color.green + Color.blue;
+ } else if (colorName == 'magenta') {
+ return Color.red + Color.blue;
+ } else if (colorName == 'cyan') {
+ return Color.green + Color.blue;
}
+ }
}
```
## 非法的合并
-TypeScript并非允许所有的合并。 目前,类不能与其它类或变量合并。 想要了解如何模仿类的合并,请参考[TypeScript的混入](mixins.md)。
+TypeScript 并非允许所有的合并。 目前,类不能与其它类或变量合并。 想要了解如何模仿类的合并,请参考[TypeScript 的混入](mixins.md)。
## 模块扩展
-虽然JavaScript不支持合并,但你可以为导入的对象打补丁以更新它们。让我们考察一下这个玩具性的示例:
+虽然 JavaScript 不支持合并,但你可以为导入的对象打补丁以更新它们。让我们考察一下这个玩具性的示例:
```typescript
// observable.ts
export class Observable