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.
tsinterface 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:
tsimport { 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:
tsimport * 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.
tsexport { read, write, standardOutput as stdout } from "./inout";
export * 可以用来重新导出另一个模块的所有导出。这对于创建汇总多个其他模块导出的模块非常有用。
tsexport 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:
tsexport default class Greeter {sayHello() {console.log("Greetings!");}}
可以使用默认导入方式导入:
🌐 Which in turn can be imported using default imports:
tsimport 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.
tsimport "./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:
tsvar { x, y, z } = getSomeObject();
解构声明也适用于从数组中提取值:
🌐 Destructuring declarations also works for extracting values from arrays:
tsvar [x, y, z = 10] = getSomeArray();
同样,解构可用于函数参数声明:
🌐 Similarly, destructuring can be used in function parameter declarations:
tsfunction 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:
tsvar x = 1;var y = 2;[x, y] = [y, x];
namespace 关键字
🌐 namespace keyword
TypeScript 使用 module 关键字来定义“内部模块”和“外部模块”;这对于刚接触 TypeScript 的开发者来说有些混淆。“内部模块”更接近大多数人所说的命名空间;同样,在 JavaScript 中,“外部模块”现在实际上就是模块。
🌐 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.
注意:以前定义内部模块的语法仍然受支持。
之前:
tsmodule Math {export function add(x, y) { ... }}
之后:
tsnamespace 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
tsconst MAX = 100;++MAX; // Error: The operand of an increment or decrement// operator cannot be a constant.
块作用域
🌐 Block scoped
tsif (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:
tsfor (var v of expr) {}
将以以下形式触发:
🌐 will be emitted as:
jsfor (var _i = 0, _a = expr; _i < _a.length; _i++) {var v = _a[_i];}
装饰器
🌐 Decorators
TypeScript 装饰器基于 ES7 装饰器提案。
装饰器是:
🌐 A decorator is:
- 一个表达式
- 结果为函数
- 以目标、名称和属性描述符作为参数
- 并可选地返回一个要安装在目标对象上的属性描述符
欲了解更多信息,请参阅 装饰器 提案。
示例
🌐 Example
装饰器 readonly 和 enumerable(false) 会在属性 method 被安装到类 C 上之前应用。这样可以让装饰器改变实现,在这种情况下,增强描述符使其 writable 为 false 且 enumerable 为 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.
tsclass 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:
tstype 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:
tsfunction 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.
使用方法:
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
tsfunction 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
jsfunction 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" /> 通知编译器需要在生成的模块的 require 调用中注入一个非 TS 模块依赖;然而,在 TS 代码中没有办法使用这个模块。
新的 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:
jsdefine(["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 文件,并继续沿父目录链向上搜索。
- 调用 tsc 时,不带任何输入文件,并使用 -project(或仅使用 -p)命令行选项指定包含 tsconfig.json 文件的目录路径。
示例
🌐 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](/tsconfig#rootDir) 指定要在输出中镜像的输入目录,而不是计算它。
--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 文件中。