From fb00d582ccb82f250742b8b80db471884a1ad46b Mon Sep 17 00:00:00 2001 From: hanyujie2002 <84226578+hanyujie2002@users.noreply.github.com> Date: Sat, 8 Jun 2024 11:56:50 +0800 Subject: [PATCH] init translation of ts for functional programmer --- .../TS for Functional Programmers.md | 380 ++++++------------ 1 file changed, 134 insertions(+), 246 deletions(-) diff --git a/docs/documentation/zh/get-started/TS for Functional Programmers.md b/docs/documentation/zh/get-started/TS for Functional Programmers.md index f1ffe1d..ca698b5 100644 --- a/docs/documentation/zh/get-started/TS for Functional Programmers.md +++ b/docs/documentation/zh/get-started/TS for Functional Programmers.md @@ -1,65 +1,48 @@ --- -title: TypeScript for Functional Programmers -short: TS for Functional Programmers +title: 面向函数式编程者的 TypeScript +short: 面向函数式编程者的 TypeScript layout: docs permalink: /zh/docs/handbook/typescript-in-5-minutes-func.html -oneline: Learn TypeScript if you have a background in functional programming +oneline: 如果你有函数式编程背景,就来学习 TypeScript 吧 --- -TypeScript began its life as an attempt to bring traditional object-oriented types -to JavaScript so that the programmers at Microsoft could bring -traditional object-oriented programs to the web. As it has developed, TypeScript's type -system has evolved to model code written by native JavaScripters. The -resulting system is powerful, interesting and messy. +TypeScript 最初的目的是为 JavaScript 引入传统的面向对象类型系统,以便微软的程序员能够将传统的面向对象程序带到 web 上。随着其发展,TypeScript 的类型系统已经演化为更好地模拟原生 JavaScript 开发者编写的代码。最终其拥有一个强大、有趣且复杂的体系。 -This introduction is designed for working Haskell or ML programmers -who want to learn TypeScript. It describes how the type system of -TypeScript differs from Haskell's type system. It also describes -unique features of TypeScript's type system that arise from its -modelling of JavaScript code. +本介绍面向具有 Haskell 或 ML 编程背景的从业者,旨在介绍 TypeScript 的类型系统如何与 Haskell 的类型系统不同。本介绍还描述了 TypeScript 类型系统中由于模拟 JavaScript 代码而产生的独特特性。 -This introduction does not cover object-oriented programming. In -practice, object-oriented programs in TypeScript are similar to those -in other popular languages with OO features. +本介绍不涉及面向对象编程。在实践中,TypeScript 中的面向对象程序与其他流行语言中的面向对象程序类似。 -## Prerequisites +## 前提条件 -In this introduction, I assume you know the following: +在本介绍中,我们假定你已经具备以下知识: -- How to program in JavaScript, the good parts. -- Type syntax of a C-descended language. +- 使用 JavaScript 的核心部分进行编程。 +- C 系列语言的类型语法。 -If you need to learn the good parts of JavaScript, read -[JavaScript: The Good Parts](https://shop.oreilly.com/product/9780596517748.do). -You may be able to skip the book if you know how to write programs in -a call-by-value lexically scoped language with lots of mutability and -not much else. -[R4RS Scheme](https://people.csail.mit.edu/jaffer/r4rs.pdf) is a good example. +如果你需要学习 JavaScript 的核心部分,请阅读[JavaScript 语言精粹](https://shop.oreilly.com/product/9780596517748.do)。如果你知道如何在一个以调用值为基础、词法作用域的语言中编程(这种语言具有大量的可变性而没有太多其他特性),那么你或许可以跳过这本书。[R4RS Scheme](https://people.csail.mit.edu/jaffer/r4rs.pdf) 就是一个很好的例子。 -[The C++ Programming Language](http://www.stroustrup.com/4th.html) is -a good place to learn about C-style type syntax. Unlike C++, -TypeScript uses postfix types, like so: `x: string` instead of `string x`. +要学习 C 风格的类型声明语法,[C++ 编程语言](http://www.stroustrup.com/4th.html)是一个不错的选择。与 C++ 不同,TypeScript 使用后缀类型注解,例如 `x: string`,而不是 `string x`。 -## Concepts not in Haskell +## Haskell 中不存在的概念 -### Built-in types +### 内置类型 -JavaScript defines 8 built-in types: +JavaScript 定义了 8 种内置类型: -| Type | Explanation | -| ----------- | ------------------------------------------- | -| `Number` | a double-precision IEEE 754 floating point. | -| `String` | an immutable UTF-16 string. | -| `BigInt` | integers in the arbitrary precision format. | -| `Boolean` | `true` and `false`. | -| `Symbol` | a unique value usually used as a key. | -| `Null` | equivalent to the unit type. | -| `Undefined` | also equivalent to the unit type. | -| `Object` | similar to records. | +| 类型 | 说明 | +| ----------- | ---------------------------------------- | +| `Number` | 双精度 IEEE 754 浮点数。 | +| `String` | 不可变的 UTF-16 字符串。 | +| `BigInt` | 以任意精度格式表示的整数。 | +| `Boolean` | `true` 和 `false`。 | +| `Symbol` | 唯一值,通常用作键。 | +| `Null` | 相当于单元类型。 | +| `Undefined` | 也相当于单元类型。 | +| `Object` | 类似于记录。 | -[See the MDN page for more detail](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures). +[请参见 MDN 页面以了解更多详细信息](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures)。 -TypeScript has corresponding primitive types for the built-in types: +TypeScript 有相应的基本类型来对应这些内置类型: - `number` - `string` @@ -70,111 +53,89 @@ TypeScript has corresponding primitive types for the built-in types: - `undefined` - `object` -#### Other important TypeScript types +#### TypeScript 的其他重要类型 -| Type | Explanation | -| -------------- | ------------------------------------------------------------------------------- | -| `unknown` | the top type. | -| `never` | the bottom type. | -| object literal | eg `{ property: Type }` | -| `void` | for functions with no documented return value | -| `T[]` | mutable arrays, also written `Array` | -| `[T, T]` | tuples, which are fixed-length but mutable | -| `(t: T) => U` | functions | +| 类型 | 说明 | +| -------------- | ------------------------------------------------------------------------ | +| `unknown` | 顶级类型。 | +| `never` | 底层类型。 | +| 对象字面量 | 例如 `{ property: Type }` | +| `void` | 无记录返回值的函数 | +| `T[]` | 可变数组,也可以写为 `Array` | +| `[T, T]` | 元组,长度固定但可变 | +| `(t: T) => U` | 函数 | -Notes: +注意: -1. Function syntax includes parameter names. This is pretty hard to get used to! +1. 函数语法包括参数名称。这让人很难习惯! ```ts let fst: (a: any, b: any) => any = (a, b) => a; - // or more precisely: + // 或更精确地: let fst: (a: T, b: U) => T = (a, b) => a; ``` -2. Object literal type syntax closely mirrors object literal value syntax: +2. 对象字面量类型语法与对象字面量值语法非常相似: ```ts let o: { n: number; xs: object[] } = { n: 1, xs: [] }; ``` -3. `[T, T]` is a subtype of `T[]`. This is different than Haskell, where tuples are not related to lists. +3. `[T, T]` 是 `T[]` 的子类型。这不同于 Haskell,在 Haskell 中元组与列表无关。 -#### Boxed types +#### 装箱类型 -JavaScript has boxed equivalents of primitive types that contain the -methods that programmers associate with those types. TypeScript -reflects this with, for example, the difference between the primitive -type `number` and the boxed type `Number`. The boxed types are rarely -needed, since their methods return primitives. +JavaScript 有基本类型的装箱等价物,包含程序员得以与这些类型相关联的方法。TypeScript 也反映了这一点,例如基本类型 `number` 和装箱类型 `Number` 之间的区别。装箱类型很少需要,因为它们的方法会返回基本类型。 ```ts (1).toExponential(); -// equivalent to +// 等价于 Number.prototype.toExponential.call(1); ``` -Note that calling a method on a numeric literal requires it to be in -parentheses to aid the parser. +请注意,要想用数字字面量调用方法,你需要将其括在括号中,以帮助解析器解析。 -### Gradual typing +### 渐进式类型 -TypeScript uses the type `any` whenever it can't tell what the type of -an expression should be. Compared to `Dynamic`, calling `any` a type -is an overstatement. It just turns off the type checker -wherever it appears. For example, you can push any value into an -`any[]` without marking the value in any way: +TypeScript 使用类型 `any` 来表示任何它无法确定表达式类型的地方。与 `Dynamic` 相比,称 `any` 为类型是一种过度陈述。它只是在任何出现的地方关闭了类型检查器。例如,你可以将任何值推入 `any[]` 而不需要以任何方式标记该值: ```ts twoslash -// with "noImplicitAny": false in tsconfig.json, anys: any[] +// 在 tsconfig.json 中设置“noImplicitAny: false”,anys: any[] const anys = []; anys.push(1); anys.push("oh no"); anys.push({ anything: "goes" }); ``` -And you can use an expression of type `any` anywhere: +并且你可以在任何地方使用类型为 `any` 的表达式: ```ts -anys.map(anys[1]); // oh no, "oh no" is not a function +anys.map(anys[1]); // oh no,“oh no”不是一个函数 ``` -`any` is contagious, too — if you initialize a variable with an -expression of type `any`, the variable has type `any` too. +`any` 也具有传染性——如果你用一个类型为 `any` 的表达式初始化一个变量,那么该变量也具有类型 `any`。 ```ts -let sepsis = anys[0] + anys[1]; // this could mean anything +let sepsis = anys[0] + anys[1]; // 这可能意味着任何东西 ``` -To get an error when TypeScript produces an `any`, use -`"noImplicitAny": true`, or `"strict": true` in `tsconfig.json`. +要在 TypeScript 产生 `any` 时报错,请在 `tsconfig.json` 中设置 `"noImplicitAny": true` 或 `"strict": true`。 -### Structural typing +### 结构类型 -Structural typing is a familiar concept to most functional -programmers, although Haskell and most MLs are not -structurally typed. Its basic form is pretty simple: +结构类型是大多数函数式编程语言的一个常见概念,尽管 Haskell 和大多数 ML 语言都不是结构类型。它的基本形式非常简单: ```ts // @strict: false -let o = { x: "hi", extra: 1 }; // ok -let o2: { x: string } = o; // ok +let o = { x: "hi", extra: 1 }; // 可以 +let o2: { x: string } = o; // 可以 ``` -Here, the object literal `{ x: "hi", extra: 1 }` has a matching -literal type `{ x: string, extra: number }`. That -type is assignable to `{ x: string }` since -it has all the required properties and those properties have -assignable types. The extra property doesn't prevent assignment, it -just makes it a subtype of `{ x: string }`. +这里,对象字面量 `{ x: "hi", extra: 1 }` 有一个匹配的字面量类型 `{ x: string, extra: number }`。这种类型可以赋值给 `{ x: string }`,因为它包含了所有必需的属性,并且这些属性的类型是可赋值的。额外的属性并不会阻止赋值,它只是使它成为 `{ x: string }` 的子类型。 -Named types just give a name to a type; for assignability purposes -there's no difference between the type alias `One` and the interface -type `Two` below. They both have a property `p: string`. (Type aliases -behave differently from interfaces with respect to recursive -definitions and type parameters, however.) +命名类型只是给类型一个名称;从可赋值性角度来说,下面的类型别名 `One` 和接口类型 `Two` 之间没有差异。它们都有属性 `p: string`。(类型别名和接口在递归定义和类型参数方面的行为是不同的。) ```ts twoslash // @errors: 2322 @@ -191,17 +152,15 @@ let two: Two = x; two = new Three(); ``` -### Unions +### 联合类型 -In TypeScript, union types are untagged. In other words, they are not -discriminated unions like `data` in Haskell. However, you can often -discriminate types in a union using built-in tags or other properties. +在 TypeScript 中,联合类型是无标签的。换句话说,它们不是像 Haskell 中的 `data` 一样的判别式联合类型。然而,你通常可以使用内置的标签或其他属性来区分联合类型中的类型。 ```ts twoslash function start( arg: string | string[] | (() => string) | { s: string } ): string { - // this is super common in JavaScript + // 这在 JavaScript 中非常常见 if (typeof arg === "string") { return commonCase(arg); } else if (Array.isArray(arg)) { @@ -213,21 +172,17 @@ function start( } function commonCase(s: string): string { - // finally, just convert a string to another string + // 最后,只需将字符串转换为另一个字符串 return s; } } ``` -`string`, `Array` and `Function` have built-in type predicates, -conveniently leaving the object type for the `else` branch. It is -possible, however, to generate unions that are difficult to -differentiate at runtime. For new code, it's best to build only -discriminated unions. +`string`、`Array` 和 `Function` 都有内置的类型谓词,可以方便地将对象类型留给 `else` 分支。但是,也可能生成难以在运行时区分的联合类型。对于新的代码,最好只构建判别式联合类型。 -The following types have built-in predicates: +以下类型有内置的谓词: -| Type | Predicate | +| 类型 | 谓词 | | --------- | ---------------------------------- | | string | `typeof s === "string"` | | number | `typeof n === "number"` | @@ -239,57 +194,45 @@ The following types have built-in predicates: | array | `Array.isArray(a)` | | object | `typeof o === "object"` | -Note that functions and arrays are objects at runtime, but have their -own predicates. +请注意,函数和数组在运行时也是对象,但有自己的谓词。 -#### Intersections +#### 交叉类型 -In addition to unions, TypeScript also has intersections: +除了联合类型,TypeScript 还有交叉类型: ```ts twoslash type Combined = { a: number } & { b: string }; type Conflicting = { a: number } & { a: string }; ``` -`Combined` has two properties, `a` and `b`, just as if they had been -written as one object literal type. Intersection and union are -recursive in case of conflicts, so `Conflicting.a: number & string`. +`Combined` 有两个属性 `a` 和 `b`,就像它们被写在一个对象字面量类型中一样。如果存在冲突,交叉和联合是递归的,所以 `Conflicting.a: number & string`。 -### Unit types +### 单元类型 -Unit types are subtypes of primitive types that contain exactly one -primitive value. For example, the string `"foo"` has the type -`"foo"`. Since JavaScript has no built-in enums, it is common to use a set of -well-known strings instead. Unions of string literal types allow -TypeScript to type this pattern: +单元类型是基本类型的子类型,只包含一个基本值。例如,字符串 `"foo"` 的类型是 `"foo"`。由于 JavaScript 没有内置的枚举,通常使用一组众所周知的字符串代替。字符串字面量类型的联合允许 TypeScript 对此模式进行类型化: ```ts twoslash declare function pad(s: string, n: number, direction: "left" | "right"): string; pad("hi", 10, "left"); ``` -When needed, the compiler _widens_ — converts to a -supertype — the unit type to the primitive type, such as `"foo"` -to `string`. This happens when using mutability, which can hamper some -uses of mutable variables: +当需要时,编译器会将单元类型*扩展*(即转换为超类型)到原始类型,例如 `"foo"` 到 `string`。这在使用可变性时会发生,可能会妨碍一些可变变量的使用: ```ts twoslash // @errors: 2345 declare function pad(s: string, n: number, direction: "left" | "right"): string; // ---cut--- let s = "right"; -pad("hi", 10, s); // error: 'string' is not assignable to '"left" | "right"' +pad("hi", 10, s); // 错误: ‘string’不可赋值给‘"left" | "right"’ ``` -Here's how the error happens: +错误发生的原因如下: - `"right": "right"` -- `s: string` because `"right"` widens to `string` on assignment to a mutable variable. -- `string` is not assignable to `"left" | "right"` +- `s: string` 因为在赋值给可变变量时,`"right"` 会扩展为 `string`。 +- `string` 不可分配给 `"left" | "right"` -You can work around this with a type annotation for `s`, but that -in turn prevents assignments to `s` of variables that are not of type -`"left" | "right"`. +你可以用类型注解解决这个问题,但这反过来又会阻止将不是 `"left" | "right"` 类型的变量赋值给 `s`。 ```ts twoslash declare function pad(s: string, n: number, direction: "left" | "right"): string; @@ -298,42 +241,32 @@ let s: "left" | "right" = "right"; pad("hi", 10, s); ``` -## Concepts similar to Haskell +## Haskell 类似的概念 -### Contextual typing +### 上下文类型推断 -TypeScript has some obvious places where it can infer types, like -variable declarations: +TypeScript 有一些明显可以推断类型的地方,比如变量声明: ```ts twoslash let s = "I'm a string!"; ``` -But it also infers types in a few other places that you may not expect -if you've worked with other C-syntax languages: +但它也会在一些你可能没有预料到的地方推断类型,如果你之前使用过其他 C 语法的语言: ```ts twoslash declare function map(f: (t: T) => U, ts: T[]): U[]; let sns = map((n) => n.toString(), [1, 2, 3]); ``` -Here, `n: number` in this example also, despite the fact that `T` and `U` -have not been inferred before the call. In fact, after `[1,2,3]` has -been used to infer `T=number`, the return type of `n => n.toString()` -is used to infer `U=string`, causing `sns` to have the type -`string[]`. +这里,`n: number` 在这个例子中也是这样,尽管 `T` 和 `U` 在调用之前还没有被推断出来。事实上,在 `[1,2,3]` 被用来推断 `T=number` 之后,`n => n.toString()` 的返回类型被用来推断 `U=string`,导致 `sns` 的类型为 `string[]`。 -Note that inference will work in any order, but intellisense will only -work left-to-right, so TypeScript prefers to declare `map` with the -array first: +请注意,推断会以任何顺序工作,但 intellisense 只会从左到右工作,所以 TypeScript 更倾向于将 `map` 声明为数组在前: ```ts twoslash declare function map(ts: T[], f: (t: T) => U): U[]; ``` -Contextual typing also works recursively through object literals, and -on unit types that would otherwise be inferred as `string` or -`number`. And it can infer return types from context: +上下文类型推断还可以递归地在对象字面量中工作,并推断出原本会被推断为 `string` 或 `number` 的单元类型。它还可以通过上下文推断返回类型: ```ts twoslash declare function run(thunk: (t: T) => void): T; @@ -342,47 +275,34 @@ let i: { inference: string } = run((o) => { }); ``` -The type of `o` is determined to be `{ inference: string }` because +`o` 的类型被确定为 `{ inference: string }`,因为: -1. Declaration initializers are contextually typed by the - declaration's type: `{ inference: string }`. -2. The return type of a call uses the contextual type for inferences, - so the compiler infers that `T={ inference: string }`. -3. Arrow functions use the contextual type to type their parameters, - so the compiler gives `o: { inference: string }`. +1. 声明初始化程序的上下文类型由声明的类型确定:`{ inference: string }`。 +2. 调用的返回类型使用上下文类型进行推断,所以编译器推断 `T={ inference: string }`。 +3. 箭头函数使用上下文类型来类型化它们的参数,所以编译器给出 `o: { inference: string }`。 -And it does so while you are typing, so that after typing `o.`, you -get completions for the property `inference`, along with any other -properties you'd have in a real program. -Altogether, this feature can make TypeScript's inference look a bit -like a unifying type inference engine, but it is not. +这一切都是在你键入时进行的,所以在键入 `o.` 之后,你会得到 `inference` 属性的补全,以及任何其他你在真实程序中会有的属性。总的来说,这个特性可以使 TypeScript 的类型推断看起来有点像一个统一的类型推断引擎,但它并不是这样。 -### Type aliases +### 类型别名 -Type aliases are mere aliases, just like `type` in Haskell. The -compiler will attempt to use the alias name wherever it was used in -the source code, but does not always succeed. +类型别名只是一个别名,就像 Haskell 中的 `type`。编译器会尝试在源代码中使用别名名称,但并不总是成功。 ```ts twoslash type Size = [number, number]; let x: Size = [101.1, 999.9]; ``` -The closest equivalent to `newtype` is a _tagged intersection_: +最接近 `newtype` 的是 _tagged 交集_: ```ts type FString = string & { __compileTimeOnly: any }; ``` -An `FString` is just like a normal string, except that the compiler -thinks it has a property named `__compileTimeOnly` that doesn't -actually exist. This means that `FString` can still be assigned to -`string`, but not the other way round. +`FString` 就像一个普通的字符串,只是编译器认为它有一个名为 `__compileTimeOnly` 的属性,实际上并不存在。这意味着 `FString` 仍然可以被赋值给 `string`,但反过来却不行。 -### Discriminated Unions +### 辨别联合类型 -The closest equivalent to `data` is a union of types with discriminant -properties, normally called discriminated unions in TypeScript: +最接近 `data` 的是带有辨别属性的类型联合,通常称为 TypeScript 中的辨别联合: ```ts type Shape = @@ -391,11 +311,7 @@ type Shape = | { kind: "triangle"; x: number; y: number }; ``` -Unlike Haskell, the tag, or discriminant, is just a property in each -object type. Each variant has an identical property with a different -unit type. This is still a normal union type; the leading `|` is -an optional part of the union type syntax. You can discriminate the -members of the union using normal JavaScript code: +与 Haskell 不同,标签或辨别符只是每个对象类型中的一个属性。每个变体都有一个相同的属性,但单元类型不同。这仍然是一个普通的联合类型;前面的 `|` 是联合类型语法中的可选部分。你可以使用普通的 JavaScript 代码来区分联合的成员: ```ts twoslash type Shape = @@ -414,12 +330,9 @@ function area(s: Shape) { } ``` -Note that the return type of `area` is inferred to be `number` because -TypeScript knows the function is total. If some variant is not -covered, the return type of `area` will be `number | undefined` instead. +请注意,`area` 的返回类型被推断为 `number`,因为 TypeScript 知道该函数是完整的。如果没有涵盖某个变体,`area` 的返回类型将是 `number | undefined`。 -Also, unlike Haskell, common properties show up in any union, so you -can usefully discriminate multiple members of the union: +另外,与 Haskell 不同,公共属性出现在任何联合中,所以你可以有效区分联合的多个成员: ```ts twoslash type Shape = @@ -437,10 +350,9 @@ function height(s: Shape) { } ``` -### Type Parameters +### 类型参数 -Like most C-descended languages, TypeScript requires declaration of -type parameters: +与大多数 C 系语言一样,TypeScript 需要声明类型参数: ```ts function liftArray(t: T): Array { @@ -448,9 +360,7 @@ function liftArray(t: T): Array { } ``` -There is no case requirement, but type parameters are conventionally -single uppercase letters. Type parameters can also be constrained to a -type, which behaves a bit like type class constraints: +这里没有大小写要求,但是类型参数通常使用单个大写字母。类型参数也可以被限制为某种类型,这有点像类型类约束: ```ts function firstish(t1: T, t2: T): T { @@ -458,14 +368,9 @@ function firstish(t1: T, t2: T): T { } ``` -TypeScript can usually infer type arguments from a call based on the -type of the arguments, so type arguments are usually not needed. +TypeScript 通常可以根据参数的类型推断出类型参数,所以通常不需要指定类型参数。 -Because TypeScript is structural, it doesn't need type parameters as -much as nominal systems. Specifically, they are not needed to make a -function polymorphic. Type parameters should only be used to -_propagate_ type information, such as constraining parameters to be -the same type: +由于 TypeScript 是结构化的,它不像名义系统那样需要大量使用类型参数。具体来说,不需要使用类型参数来使一个函数具有多态性。类型参数应该只用于*传播*类型信息,比如限制参数必须是相同的类型: ```ts function length>(t: T): number {} @@ -473,31 +378,23 @@ function length>(t: T): number {} function length(t: ArrayLike): number {} ``` -In the first `length`, T is not necessary; notice that it's only -referenced once, so it's not being used to constrain the type of the -return value or other parameters. +在第一个 `length` 中,T 是不必要的;请注意,它只被引用了一次,所以它不用于限制返回值或其他参数的类型。 -#### Higher-kinded types +#### 高阶类型 -TypeScript does not have higher kinded types, so the following is not legal: +TypeScript 没有高阶类型,所以以下代码是无效的: ```ts function length, U>(m: T) {} ``` -#### Point-free programming +#### 无点编程 -Point-free programming — heavy use of currying and function -composition — is possible in JavaScript, but can be verbose. -In TypeScript, type inference often fails for point-free programs, so -you'll end up specifying type parameters instead of value parameters. The -result is so verbose that it's usually better to avoid point-free -programming. +在 JavaScript 中,无点编程(大量使用柯里化和函数组合)是可行的,但可能会很冗长。在 TypeScript 中,无点编程的类型推断往往会失败,所以最终你虽然不需要指定值参数,但需要指定类型参数。结果太冗长了,所以通常最好避免使用无点编程。 -### Module system +### 模块系统 -JavaScript's modern module syntax is a bit like Haskell's, except that -any file with `import` or `export` is implicitly a module: +JavaScript 的现代模块语法有点类似 Haskell,只不过任何包含 `import` 或 `export` 的文件都是一个模块: ```ts import { value, Type } from "npm-package"; @@ -505,14 +402,13 @@ import { other, Types } from "./local-package"; import * as prefix from "../lib/third-package"; ``` -You can also import commonjs modules — modules written using node.js' -module system: +你也可以导入 CommonJS 模块(使用 Node.js 模块系统编写的模块): ```ts import f = require("single-function-package"); ``` -You can export with an export list: +你可以使用导出列表导出: ```ts export { f }; @@ -520,24 +416,21 @@ export { f }; function f() { return g(); } -function g() {} // g is not exported +function g() {} // g 没有被导出 ``` -Or by marking each export individually: +或者将每个导出单独标记: ```ts export function f() { return g() } function g() { } ``` -The latter style is more common but both are allowed, even in the same -file. +后一种方式更常见,但两种方式都可行的,甚至在单个文件中可以同时使用。 -### `readonly` and `const` +### `readonly` 和 `const` -In JavaScript, mutability is the default, although it allows variable -declarations with `const` to declare that the _reference_ is -immutable. The referent is still mutable: +在 JavaScript 中,可变性是默认的,尽管它允许使用 `const` 进行变量声明(其声明*引用*是不可变的),但引用的内容仍然是可变的: ```js const a = [1, 2, 3]; @@ -545,53 +438,48 @@ a.push(102); // ): a[0] = 101; // D: ``` -TypeScript additionally has a `readonly` modifier for properties. +TypeScript 还有一个 `readonly` 修饰符用来修饰属性。 ```ts interface Rx { readonly x: number; } let rx: Rx = { x: 1 }; -rx.x = 12; // error +rx.x = 12; // 错误 ``` -It also ships with a mapped type `Readonly` that makes -all properties `readonly`: +它还附带映射类型 `Readonly`,可以将所有属性设置为 `readonly`: ```ts interface X { x: number; } let rx: Readonly = { x: 1 }; -rx.x = 12; // error +rx.x = 12; // 错误 ``` -And it has a specific `ReadonlyArray` type that removes -side-affecting methods and prevents writing to indices of the array, -as well as special syntax for this type: +它还有一个特定的 `ReadonlyArray` 类型,可以移除有副作用的方法,并防止写入数组索引,同时这种类型的特殊的语法也会移除: ```ts let a: ReadonlyArray = [1, 2, 3]; let b: readonly number[] = [1, 2, 3]; -a.push(102); // error -b[0] = 101; // error +a.push(102); // 错误 +b[0] = 101; // 错误 ``` -You can also use a const-assertion, which operates on arrays and -object literals: +你也可以使用 const 断言,它可以作用于数组和对象字面量: ```ts let a = [1, 2, 3] as const; -a.push(102); // error -a[0] = 101; // error +a.push(102); // 错误 +a[0] = 101; // 错误 ``` -However, none of these options are the default, so they are not -consistently used in TypeScript code. +但是,这些选项都不是默认的,所以在 TypeScript 代码中并不总是一致地使用。 -### Next Steps +### 下一步 -This doc is a high level overview of the syntax and types you would use in everyday code. From here you should: +本文档是日常代码中使用的语法和类型的概述。之后你应该: -- Read the full Handbook [from start to finish](/zh/docs/handbook/intro.html) -- Explore the [Playground examples](/play#show-examples) +- [从头到尾](/zh/docs/handbook/intro.html)阅读完整的手册 +- 探索[演练场的示例](/play#show-examples)