Skip to content

Commit f18438c

Browse files
translate TS for JS Programmers.md in zh-CN
1 parent 5c0157b commit f18438c

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
---
2+
title: 为 JavaScript 程序员准备的 TypeScript
3+
short: 为 JS 程序员准备的 TypeScript
4+
layout: docs
5+
permalink: /zh/docs/handbook/typescript-in-5-minutes.html
6+
oneline: 学习 TypeScript 对 Javascript 的扩展
7+
---
8+
9+
TypeScript 与 JavaScript 有着不同寻常的关系。TypeScript 提供了 JavaScript 的所有功能,并在这些功能之上添加了一层: TypeScript 的类型系统。
10+
11+
例如,JavaScript 提供了诸如 `string``number` 这样的原始类型,但它不检查你在赋值时与类型是否匹配。TypeScript 提供了这样的功能。
12+
13+
这意味着你现有的运行良好的 JavaScript 代码也是 TypeScript 代码。TypeScript 的主要好处是,它可以检查代码中的意外行为,从而降低出现错误的机会。
14+
15+
本教程提供 TypeScript 的简要概述,重点介绍其类型系统。
16+
17+
## 类型推断
18+
19+
TypeScript 可以识别 JavaScript 语言,在许多情况下可以推断类型。例如,在创建变量并将其赋值给特定值时, TypeScript 将使用该值作为其类型。
20+
21+
```ts twoslash
22+
let helloWorld = "Hello World";
23+
// ^?
24+
```
25+
26+
通过感知 JavaScript 的工作原理,TypeScript 可以构建一个接受 JavaScript 代码但具有类型的类型系统。这个类型系统使得我们不需要添加额外的字符来显式地指定类型。在上面的例子中,TypeScript就是这样知道 `helloWorld``string` 类型的。
27+
28+
你可能已经在 Visual Studio Code 中编写了 JavaScript,并已使用了编辑器的自动补全功能。Visual Studio Code 使用了 TypeScript 的引擎,以便更容易地处理 JavaScript。
29+
30+
## 定义类型
31+
32+
你可以在 JavaScript 中使用各种各样的设计模式。然而,某些设计模式使得类型难以自动推断(例如,使用动态编程的模式)。为了使类型推断涵盖这些情况, TypeScript 支持扩展 JavaScript 语言,它可以让 TypeScript 知道如何去推断类型。
33+
34+
例如,要创建具有推断类型的对象,该类型包括 `name: string``id: number`,你可以这么写:
35+
36+
```ts twoslash
37+
const user = {
38+
name: "Hayes",
39+
id: 0,
40+
};
41+
```
42+
43+
你可以使用 `interface` 关键字声明显式地描述此对象的*内部数据的类型*(译者注:下文可能译为“结构”):
44+
45+
```ts twoslash
46+
interface User {
47+
name: string;
48+
id: number;
49+
}
50+
```
51+
52+
然后你可以声明一个符合此接口(`interface`)的 JavaScript 对象,在变量声明后使用像 `: TypeName` 这样的语法:
53+
54+
```ts twoslash
55+
interface User {
56+
name: string;
57+
id: number;
58+
}
59+
// ---分割线---
60+
const user: User = {
61+
name: "Hayes",
62+
id: 0,
63+
};
64+
```
65+
66+
如果提供的对象与提供的接口不匹配,TypeScript 将警告:
67+
68+
```ts twoslash
69+
// @errors: 2322
70+
interface User {
71+
name: string;
72+
id: number;
73+
}
74+
75+
const user: User = {
76+
username: "Hayes",
77+
id: 0,
78+
};
79+
```
80+
81+
由于 JavaScript 支持类和面向对象编程,TypeScript 也支持。你可以将接口声明与类一起使用:
82+
83+
```ts twoslash
84+
interface User {
85+
name: string;
86+
id: number;
87+
}
88+
89+
class UserAccount {
90+
name: string;
91+
id: number;
92+
93+
constructor(name: string, id: number) {
94+
this.name = name;
95+
this.id = id;
96+
}
97+
}
98+
99+
const user: User = new UserAccount("Murphy", 1);
100+
```
101+
102+
您可以使用接口对参数进行注释,并将值返回给函数:
103+
104+
```ts twoslash
105+
// @noErrors
106+
interface User {
107+
name: string;
108+
id: number;
109+
}
110+
// ---分割线---
111+
function getAdminUser(): User {
112+
//...
113+
}
114+
115+
function deleteUser(user: User) {
116+
// ...
117+
}
118+
```
119+
120+
JavaScript 中已经有一些基本类型可用:`boolean``bigint``null``number``string``symbol ``undefined`,它们都可以在接口中使用。TypeScript 将此列表扩展为更多的内容,例如 `any` (允许任何类型)、[`unknown`](/play#example/unknown-and-never) (确保使用此类型的人声明类型是什么)、 [`never`](/play#example/unknown-and-never) (这种类型不可能发生)和 `void` (返回 `undefined` 或没有返回值的函数)。
121+
122+
构建类型有两种语法: [接口和类型](/play/?e=83#example/types-vs-interfaces)。 你应该更喜欢 `interface`。当需要特定功能时使用 `type`
123+
124+
## 组合类型
125+
126+
使用 TypeScript,可以通过组合简单类型来创建复杂类型。有两种流行的方法可以做到这一点:联合和泛型。
127+
128+
### 联合
129+
130+
使用联合,可以声明类型可以是许多类型中的一种。例如,可以将 `boolean` 类型描述为 `true``false`
131+
132+
```ts twoslash
133+
type MyBool = true | false;
134+
```
135+
136+
_注意:_如果将鼠标悬停在上面的 `MyBool` 上,您将看到它被归类为 `boolean`。这是结构化类型系统的一个属性。下面有更加详细的信息。
137+
138+
联合类型的一个流行用法是描述 `string` 或者 `number`[字面量](/docs/handbook/2/everyday-types.html#literal-types)的合法值。
139+
140+
```ts twoslash
141+
type WindowStates = "open" | "closed" | "minimized";
142+
type LockStates = "locked" | "unlocked";
143+
type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
144+
```
145+
146+
联合也提供了一种处理不同类型的方法。例如,可能有一个函数处理 `array` 或者 `string`
147+
148+
```ts twoslash
149+
function getLength(obj: string | string[]) {
150+
return obj.length;
151+
}
152+
```
153+
154+
要了解变量的类型, 使用 `typeof`
155+
156+
| 类型 | 推断语句 |
157+
| --------- | ---------------------------------- |
158+
| string | `typeof s === "string"` |
159+
| number | `typeof n === "number"` |
160+
| boolean | `typeof b === "boolean"` |
161+
| undefined | `typeof undefined === "undefined"` |
162+
| function | `typeof f === "function"` |
163+
| array | `Array.isArray(a)` |
164+
165+
例如,你可以使函数根据传递的是字符串还是数组返回不同的值:
166+
167+
<!-- prettier-ignore -->
168+
```ts twoslash
169+
function wrapInArray(obj: string | string[]) {
170+
if (typeof obj === "string") {
171+
return [obj];
172+
// ^?
173+
}
174+
return obj;
175+
}
176+
```
177+
178+
### 泛型
179+
180+
泛型为类型提供变量。一个常见的例子是数组。没有泛型的数组可以包含任何内容。带有泛型的数组可以描述数组包含的值。
181+
182+
```ts
183+
type StringArray = Array<string>;
184+
type NumberArray = Array<number>;
185+
type ObjectWithNameArray = Array<{ name: string }>;
186+
```
187+
188+
你可以声明自己使用泛型的类型:
189+
190+
```ts twoslash
191+
// @errors: 2345
192+
interface Backpack<Type> {
193+
add: (obj: Type) => void;
194+
get: () => Type;
195+
}
196+
197+
// 这一行是一个简写,可以告诉 TypeScript 有一个常量,叫做`backpack`,并且不用担心它是从哪
198+
// 里来的。
199+
declare const backpack: Backpack<string>;
200+
201+
// 对象是一个字符串,因为我们在上面声明了它作为 Backpack 的变量部分。
202+
const object = backpack.get();
203+
204+
// 因为 backpack 变量是一个字符串,不能将数字传递给 add 函数。
205+
backpack.add(23);
206+
```
207+
208+
## 结构化的类型系统(structural type system)
209+
210+
TypeScript 的一个核心原则是类型检查基于对象的属性和行为(type checking focuses on the _shape_ that values have)。这有时被叫做“鸭子类型”或“结构类型”(structural typing)。
211+
212+
在结构化的类型系统当中,如果两个对象具有相同的结构,则认为它们是相同类型的。
213+
214+
```ts twoslash
215+
interface Point {
216+
x: number;
217+
y: number;
218+
}
219+
220+
function logPoint(p: Point) {
221+
console.log(`${p.x}, ${p.y}`);
222+
}
223+
224+
// 打印 "12, 26"
225+
const point = { x: 12, y: 26 };
226+
logPoint(point);
227+
```
228+
229+
`point` 变量从未声明为 `Point` 类型。 但是,在类型检查中,TypeScript 将 `point` 的结构与 `Point`的结构进行比较。它们的结构相同,所以代码通过了。
230+
231+
结构匹配只需要匹配对象字段的子集。
232+
233+
```ts twoslash
234+
// @errors: 2345
235+
interface Point {
236+
x: number;
237+
y: number;
238+
}
239+
240+
function logPoint(p: Point) {
241+
console.log(`${p.x}, ${p.y}`);
242+
}
243+
// ---cut---
244+
const point3 = { x: 12, y: 26, z: 89 };
245+
logPoint(point3); // 打印 "12, 26"
246+
247+
const rect = { x: 33, y: 3, width: 30, height: 80 };
248+
logPoint(rect); // 打印 "33, 3"
249+
250+
const color = { hex: "#187ABF" };
251+
logPoint(color);
252+
```
253+
254+
类和对象确定结构的方式没有区别:
255+
256+
```ts twoslash
257+
// @errors: 2345
258+
interface Point {
259+
x: number;
260+
y: number;
261+
}
262+
263+
function logPoint(p: Point) {
264+
console.log(`${p.x}, ${p.y}`);
265+
}
266+
// ---分割线---
267+
class VirtualPoint {
268+
x: number;
269+
y: number;
270+
271+
constructor(x: number, y: number) {
272+
this.x = x;
273+
this.y = y;
274+
}
275+
}
276+
277+
const newVPoint = new VirtualPoint(13, 56);
278+
logPoint(newVPoint); // 打印 "13, 56"
279+
```
280+
281+
如果对象或类具有所有必需的属性,则 TypeScript 将表示是它们匹配的,而不关注其实现细节。
282+
283+
## 下一步
284+
285+
这是对一般的 TypeScript 中使用的语法和工具的简要概述。参见:
286+
287+
- 阅读完整手册[由始至终](/docs/handbook/intro.html) (30 分钟)
288+
- 探索 [Playground 上的示例](/play#show-examples)
289+

0 commit comments

Comments
 (0)