ES6 模块
¥ES6 Modules
TypeScript 1.5 支持 ECMAScript 6 (ES6) 模块。ES6 模块实际上是具有新语法的 TypeScript 外部模块:ES6 模块是单独加载的源文件,可能导入其他模块并提供多个外部可访问的导出。ES6 模块具有几个新的导出和导入声明。建议更新 TypeScript 库和应用以使用新语法,但这不是必需的。新的 ES6 模块语法与 TypeScript 原有的内部和外部模块结构共存,并且可以随意混合搭配使用。
¥TypeScript 1.5 supports ECMAScript 6 (ES6) modules. ES6 modules are effectively TypeScript external modules with a new syntax: ES6 modules are separately loaded source files that possibly import other modules and provide a number of externally accessible exports. ES6 modules feature several new export and import declarations. It is recommended that TypeScript libraries and applications be updated to use the new syntax, but this is not a requirement. The new ES6 module syntax coexists with TypeScript’s original internal and external module constructs and the constructs can be mixed and matched at will.
导出声明
¥Export Declarations
除了现有的 TypeScript 支持使用 export
修饰声明之外,模块成员还可以使用单独的导出声明进行导出,并可选择使用 as
子句为导出指定不同的名称。
¥In addition to the existing TypeScript support for decorating declarations with export
, module members can also be exported using separate export declarations, optionally specifying different names for exports using as
clauses.
ts
interface Stream { ... }function writeToStream(stream: Stream, data: string) { ... }export { Stream, writeToStream as write }; // writeToStream exported as write
导入声明也可以选择使用 as
子句为导入指定不同的本地名称。例如:
¥Import declarations, as well, can optionally use as
clauses to specify different local names for the imports. For example:
ts
import { read, write, standardOutput as stdout } from "./inout";var s = read(stdout);write(stdout, s);
作为单独导入的替代方案,可以使用命名空间导入来导入整个模块:
¥As an alternative to individual imports, a namespace import can be used to import an entire module:
ts
import * as io from "./inout";var s = io.read(io.standardOutput);io.write(io.standardOutput, s);
重新导出
¥Re-exporting
使用 from
子句,模块可以将给定模块的导出复制到当前模块,而无需引入本地名称。
¥Using from
clause a module can copy the exports of a given module to the current module without introducing local names.
ts
export { read, write, standardOutput as stdout } from "./inout";
export *
可用于重新导出另一个模块的所有导出。这对于创建聚合多个其他模块导出的模块很有用。
¥export *
can be used to re-export all exports of another module. This is useful for creating modules that aggregate the exports of several other modules.
ts
export function transform(s: string): string { ... }export * from "./mod1";export * from "./mod2";
默认导出
¥Default Export
导出默认声明指定了一个表达式,该表达式将成为模块的默认导出:
¥An export default declaration specifies an expression that becomes the default export of a module:
ts
export default class Greeter {sayHello() {console.log("Greetings!");}}
可以使用默认导入方式导入:
¥Which in turn can be imported using default imports:
ts
import Greeter from "./greeter";var g = new Greeter();g.sayHello();
裸导入
¥Bare Import
“裸导入” 仅可用于导入模块以产生副作用。
¥A “bare import” can be used to import a module only for its side-effects.
ts
import "./polyfills";
有关模块的更多信息,请参阅 ES6 模块支持规范。
¥For more information about module, please see the ES6 module support spec.
声明和赋值中的解构
¥Destructuring in declarations and assignments
TypeScript 1.5 增加了对 ES6 解构声明和赋值的支持。
¥TypeScript 1.5 adds support to ES6 destructuring declarations and assignments.
声明
¥Declarations
解构声明引入一个或多个命名变量,并使用从对象属性或数组元素中提取的值来初始化它们。
¥A destructuring declaration introduces one or more named variables and initializes them with values extracted from properties of an object or elements of an array.
例如,以下示例声明变量 x
、y
和 z
,并分别将它们初始化为 getSomeObject().x
、getSomeObject().y
和 getSomeObject().z
:
¥For example, the following sample declares variables x
, y
, and z
, and initializes them to getSomeObject().x
, getSomeObject().y
and getSomeObject().z
respectively:
ts
var { x, y, z } = getSomeObject();
解构声明也适用于从数组中提取值:
¥Destructuring declarations also works for extracting values from arrays:
ts
var [x, y, z = 10] = getSomeArray();
同样,解构可用于函数参数声明:
¥Similarly, destructuring can be used in function parameter declarations:
ts
function drawText({ text = "", location: [x, y] = [0, 0], bold = false }) {// Draw text}// Call drawText with an object literalvar item = { text: "someText", location: [1, 2, 3], style: "italics" };drawText(item);
赋值
¥Assignments
解构模式也可以用于正则赋值表达式。例如,交换两个变量可以写成一个解构赋值:
¥Destructuring patterns can also be used in regular assignment expressions. For instance, swapping two variables can be written as a single destructuring assignment:
ts
var x = 1;var y = 2;[x, y] = [y, x];
namespace
关键字
¥namespace
keyword
TypeScript 使用 module
关键字来定义 “内部模块” 和 “外部模块”;这给 TypeScript 新手带来了一些困惑。“内部模块” 更接近大多数人所说的命名空间;同样,JS 中的 “外部模块” 现在实际上就是模块。
¥TypeScript used the module
keyword to define both “internal modules” and “external modules”;
this has been a bit of confusion for developers new to TypeScript.
“Internal modules” are closer to what most people would call a namespace; likewise, “external modules” in JS speak really just are modules now.
注意:以前定义内部模块的语法仍然受支持。
¥Note: Previous syntax defining internal modules are still supported.
之前:
¥Before:
ts
module Math {export function add(x, y) { ... }}
之后:
¥After:
ts
namespace Math {export function add(x, y) { ... }}
let
和 const
支持
¥let
and const
support
现在,当以 ES3 和 ES5 为目标平台时,支持 ES6 let
和 const
声明。
¥ES6 let
and const
declarations are now supported when targeting ES3 and ES5.
常量
¥Const
ts
const MAX = 100;++MAX; // Error: The operand of an increment or decrement// operator cannot be a constant.
块作用域
¥Block scoped
ts
if (true) {let a = 4;// use a} else {let a = "string";// use a}alert(a); // Error: a is not defined in this scope.
for..of 支持
¥for..of support
TypeScript 1.5 增加了对 ES3/ES5 数组 for..of 循环的支持,以及对 ES6 迭代器接口的完全支持。
¥TypeScript 1.5 adds support to ES6 for..of loops on arrays for ES3/ES5 as well as full support for Iterator interfaces when targeting ES6.
示例
¥Example
TypeScript 编译器会将 for..of 数组转换为符合 ES3/ES5 语言习惯的 JavaScript 代码,前提是这些版本:
¥The TypeScript compiler will transpile for..of arrays to idiomatic ES3/ES5 JavaScript when targeting those versions:
ts
for (var v of expr) {}
将以以下形式触发:
¥will be emitted as:
js
for (var _i = 0, _a = expr; _i < _a.length; _i++) {var v = _a[_i];}
装饰器
¥Decorators
TypeScript 装饰器基于 ES7 装饰器提案。
¥TypeScript decorators are based on the ES7 decorator proposal.
装饰器是:
¥A decorator is:
-
一个表达式
¥an expression
-
结果为函数
¥that evaluates to a function
-
以目标、名称和属性描述符作为参数
¥that takes the target, name, and property descriptor as arguments
-
并可选地返回一个要安装在目标对象上的属性描述符
¥and optionally returns a property descriptor to install on the target object
更多信息,请参阅 装饰器 提案。
¥For more information, please see the Decorators proposal.
示例
¥Example
装饰器 readonly
和 enumerable(false)
将在属性 method
安装到类 C
之前应用于它。这使得装饰器可以更改实现,在本例中,将描述符扩充为可写:false 和可枚举:false。
¥Decorators readonly
and enumerable(false)
will be applied to the property method
before it is installed on class C
.
This allows the decorator to change the implementation, and in this case, augment the descriptor to be writable: false and enumerable: false.
ts
class C {@readonly@enumerable(false)method() { ... }}function readonly(target, key, descriptor) {descriptor.writable = false;}function enumerable(value) {return function (target, key, descriptor) {descriptor.enumerable = value;};}
计算属性
¥Computed properties
初始化具有动态属性的对象可能会有点麻烦。举个例子:
¥Initializing an object with dynamic properties can be a bit of a burden. Take the following example:
ts
type NeighborMap = { [name: string]: Node };type Node = { name: string; neighbors: NeighborMap };function makeNode(name: string, initialNeighbor: Node): Node {var neighbors: NeighborMap = {};neighbors[initialNeighbor.name] = initialNeighbor;return { name: name, neighbors: neighbors };}
此处,我们需要创建一个变量来保存邻居映射,以便对其进行初始化。使用 TypeScript 1.5,我们可以让编译器完成繁重的工作:
¥Here we need to create a variable to hold on to the neighbor-map so that we can initialize it. With TypeScript 1.5, we can let the compiler do the heavy lifting:
ts
function makeNode(name: string, initialNeighbor: Node): Node {return {name: name,neighbors: {[initialNeighbor.name]: initialNeighbor,},};}
支持 UMD
和 System
模块输出
¥Support for UMD
and System
module output
除了 AMD
和 CommonJS
模块加载器之外,TypeScript 现在还支持触发模块 UMD
(通用模块定义) 和 System
模块格式。
¥In addition to AMD
and CommonJS
module loaders, TypeScript now supports emitting modules UMD
(Universal Module Definition) and System
module formats.
用法:
¥Usage:
tsc —module umd
and
tsc —module system
字符串中的 Unicode 代码点转义
¥Unicode codepoint escapes in strings
ES6 引入了转义符,允许用户仅使用单个转义符来表示 Unicode 代码点。
¥ES6 introduces escapes that allow users to represent a Unicode codepoint using just a single escape.
例如,考虑需要转义包含字符 ’𠮷’ 的字符串。在 UTF-16/UCS2 中,’𠮷’ 表示为代理对,这意味着它使用一对 16 位值的代码单元进行编码,具体来说是 0xD842
和 0xDFB7
。以前,这意味着你必须将代码点转义为 "\uD842\uDFB7"
。这有一个主要缺点,即很难从代理对中辨别出两个独立的字符。
¥As an example, consider the need to escape a string that contains the character ’𠮷‘.
In UTF-16/UCS2, ’𠮷’ is represented as a surrogate pair, meaning that it’s encoded using a pair of 16-bit code units of values, specifically 0xD842
and 0xDFB7
.
Previously this meant that you’d have to escape the codepoint as "\uD842\uDFB7"
.
This has the major downside that it’s difficult to discern two independent characters from a surrogate pair.
使用 ES6 的代码点转义,你可以使用单个转义清晰地表示字符串和模板字符串中的精确字符:"\u{20bb7}"
。TypeScript 将在 ES3/ES5 中将字符串输出为 "\uD842\uDFB7"
。
¥With ES6’s codepoint escapes, you can cleanly represent that exact character in strings and template strings with a single escape: "\u{20bb7}"
.
TypeScript will emit the string in ES3/ES5 as "\uD842\uDFB7"
.
ES3/ES5 中的带标签的模板字符串
¥Tagged template strings in ES3/ES5
在 TypeScript 1.4 中,我们为所有目标平台添加了对模板字符串的支持,并为 ES6 添加了带标签的模板。感谢 @ivogabe 所做的大量工作,我们弥补了 ES3 和 ES5 中标记模板之间的差距。
¥In TypeScript 1.4, we added support for template strings for all targets, and tagged templates for just ES6. Thanks to some considerable work done by @ivogabe, we bridged the gap for tagged templates in ES3 and ES5.
当目标语言为 ES3/ES5 时,以下代码
¥When targeting ES3/ES5, the following code
ts
function oddRawStrings(strs: TemplateStringsArray, n1, n2) {return strs.raw.filter((raw, index) => index % 2 === 1);}oddRawStrings`Hello \n${123} \t ${456}\n world`;
将以以下形式触发
¥will be emitted as
js
function oddRawStrings(strs, n1, n2) {return strs.raw.filter(function (raw, index) {return index % 2 === 1;});}(_a = ["Hello \n", " \t ", "\n world"]),(_a.raw = ["Hello \\n", " \\t ", "\\n world"]),oddRawStrings(_a, 123, 456);var _a;
AMD 依赖可选名称
¥AMD-dependency optional names
/// <amd-dependency path="x" />
会通知编译器,在生成的模块的必要调用中需要注入一个非 TS 模块依赖;然而,在 TS 代码中无法使用此模块。
¥/// <amd-dependency path="x" />
informs the compiler about a non-TS module dependency that needs to be injected in the resulting module’s required call;
however, there was no way to consume this module in the TS code.
新的 amd-dependency name
属性允许为 amd 依赖传递可选名称:
¥The new amd-dependency name
property allows passing an optional name for an amd-dependency:
ts
/// <amd-dependency path="legacy/moduleA" name="moduleA"/>declare var moduleA: MyType;moduleA.callStuff();
生成的 JS 代码:
¥Generated JS code:
js
define(["require", "exports", "legacy/moduleA"], function (require,exports,moduleA) {moduleA.callStuff();});
通过 tsconfig.json
获得项目支持
¥Project support through tsconfig.json
在目录中添加 tsconfig.json
文件表示该目录是 TypeScript 项目的根目录。tsconfig.json 文件指定了编译项目所需的根文件和编译器选项。项目通过以下方式之一编译:
¥Adding a tsconfig.json
file in a directory indicates that the directory is the root of a TypeScript project.
The tsconfig.json file specifies the root files and the compiler options required to compile the project. A project is compiled in one of the following ways:
-
调用 tsc 时,不带任何输入文件,编译器会从当前目录开始向上搜索 tsconfig.json 文件,并继续沿父目录链向上搜索。
¥By invoking tsc with no input files, in which case the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain.
-
调用 tsc 时,不带任何输入文件,并使用 -project(或仅使用 -p)命令行选项指定包含 tsconfig.json 文件的目录路径。
¥By invoking tsc with no input files and a -project (or just -p) command line option that specifies the path of a directory containing a tsconfig.json file.
示例
¥Example
{" ": {" ": "commonjs"," ": true," ": true}}
有关详细信息,请参阅 tsconfig.json 维基页面。
¥See the tsconfig.json wiki page for more details.
--rootDir
命令行选项
¥--rootDir
command line option
选项 outDir
会在输出中复制输入层次结构。编译器将输入文件的根计算为所有输入文件的最长公共路径;然后使用它在输出中复制其所有子结构。
¥Option outDir
duplicates the input hierarchy in the output.
The compiler computes the root of the input files as the longest common path of all input files;
and then uses that to replicate all its substructure in the output.
有时这并不理想,例如,输入 FolderA\FolderB\1.ts
和 FolderA\FolderB\2.ts
会导致输出结构与 FolderA\FolderB\
镜像。现在,如果将新文件 FolderA\3.ts
添加到输入,则输出结构将弹出以镜像 FolderA\
。
¥Sometimes this is not desirable, for instance inputs FolderA\FolderB\1.ts
and FolderA\FolderB\2.ts
would result in output structure mirroring FolderA\FolderB\
.
Now if a new file FolderA\3.ts
is added to the input, the output structure will pop out to mirror FolderA\
.
rootDir
指定要在输出中镜像而不是计算的输入目录。
¥rootDir
specifies the input directory to be mirrored in output instead of computing it.
--noEmitHelpers
命令行选项
¥--noEmitHelpers
command line option
TypeScript 编译器还会在需要时触发一些辅助函数,例如 __extends
。这些辅助函数会在每个引用它们的文件中触发。如果你想将所有辅助程序合并到一个地方,或者覆盖默认行为,请使用 noEmitHelpers
指示编译器不要触发它们。
¥The TypeScript compiler emits a few helpers like __extends
when needed.
The helpers are emitted in every file they are referenced in.
If you want to consolidate all helpers in one place, or override the default behavior, use noEmitHelpers
to instruct the compiler not to emit them.
--newLine
命令行选项
¥--newLine
command line option
默认情况下,在基于 Windows 的系统上,输出换行符为 \r\n
,在基于 *nix 的系统上,输出换行符为 \n
。newLine
命令行标志允许覆盖此行为并指定要在生成的输出文件中使用的换行符。
¥By default the output new line character is \r\n
on Windows based systems and \n
on *nix based systems.
newLine
command line flag allows overriding this behavior and specifying the new line character to be used in generated output files.
--inlineSourceMap
和 inlineSources
命令行选项
¥--inlineSourceMap
and inlineSources
command line options
inlineSourceMap
使源映射文件以内联方式写入生成的 .js
文件中,而不是写入独立的 .js.map
文件中。inlineSources
允许将源 .ts
文件内联到 .js
文件中。
¥inlineSourceMap
causes source map files to be written inline in the generated .js
files instead of in an independent .js.map
file.
inlineSources
allows for additionally inlining the source .ts
file into the .js
file.