TypeScript 1.5

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.

例如,以下示例声明变量 xyz,并分别将它们初始化为 getSomeObject().xgetSomeObject().ygetSomeObject().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 literal
var 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) { ... }
}

letconst 支持

¥let and const support

现在,当以 ES3 和 ES5 为目标平台时,支持 ES6 letconst 声明。

¥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

装饰器 readonlyenumerable(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,
},
};
}

支持 UMDSystem 模块输出

¥Support for UMD and System module output

除了 AMDCommonJS 模块加载器之外,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 位值的代码单元进行编码,具体来说是 0xD8420xDFB7。以前,这意味着你必须将代码点转义为 "\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.tsFolderA\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 的系统上,输出换行符为 \nnewLine 命令行标志允许覆盖此行为并指定要在生成的输出文件中使用的换行符。

¥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.

--inlineSourceMapinlineSources 命令行选项

¥--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.