TypeScript 1.5

TypeScript 1.5

ES6 模块

TypeScript 1.5 支持 ECMAScript 6(ES6)模块。ES6 模块实际上是 TypeScript 外部模块的新语法:ES6 模块是单独加载的源文件,可能导入其他模块并提供大量可从外部访问的导出。ES6 模块具有几个新的导出和导入声明。建议将 TypeScript 库和应用程序更新为使用新语法,但这不是必需的。新的 ES6 模块语法与 TypeScript 原有的内部和外部模块结构共存,并且可以随意混合和匹配结构。

导出声明

除了现有的export用于装饰声明的 TypeScript 支持外,还可以使用单独的导出声明导出模块成员,可以使用as子句为导出指定不同的名称。

interface Stream { ... } function writeToStream(stream: Stream, data: string) { ... } export { Stream, writeToStream as write }; // writeToStream exported as write

导入声明也可以选择使用as子句为导入指定不同的本地名称。例如:

import { read, write, standardOutput as stdout } from "./inout"; var s = read(stdout write(stdout, s

作为单个导入的替代方法,可以使用名称空间导入来导入整个模块:

import * as io from "./inout"; var s = io.read(io.standardOutput io.write(io.standardOutput, s

再出口

使用from子句模块可以将给定模块的输出复制到当前模块而不引入本地名称。

export { read, write, standardOutput as stdout } from "./inout";

export *可以用来重新导出另一个模块的所有导出。这对创建汇总其他几个模块的输出的模块很有用。

export function transform(s: string): string { ... } export * from "./mod1"; export * from "./mod2";

默认导出

导出默认声明指定成为模块的默认导出的表达式:

export default class Greeter { sayHello() { console.log("Greetings!" } }

哪些内容可以使用默认导入导入:

import Greeter from "./greeter"; var g = new Greeter( g.sayHello(

裸露进口

“裸导入”可以用于导入模块仅用于其副作用。

import "./polyfills";

有关模块的更多信息,请参阅 ES6模块支持规范

在声明和作业中解构

TypeScript 1.5 增加了对 ES6 解构声明和赋值的支持。

声明

解构声明引入一个或多个命名变量,并使用从对象的属性或数组元素中提取的值对它们进行初始化。

例如,下面的示例声明变量xyz,并且将它们初始化为getSomeObject().xgetSomeObject().ygetSomeObject().z分别为:

var { x, y, z} = getSomeObject(

解构声明也适用于从数组中提取值:

var [x, y, z = 10] = getSomeArray(

同样,解构可以用在函数参数声明中:

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

分配

解构模式也可用于常规赋值表达式。例如,交换两个变量可以写成单个解构赋值:

var x = 1; var y = 2; [x, y] = [y, x];

namespace 关键词

TypeScript 使用module关键字来定义“内部模块”和“外部模块”; 这对于新开发 TypeScript 的开发者来说有点混乱。“内部模块”更接近大多数人称之为命名空间的东西; 同样,JS 中的“外部模块”现在真的只是模块。

注:仍然支持先前定义内部模块的语法。

之前

module Math { export function add(x, y) { ... } }

之后

namespace Math { export function add(x, y) { ... } }

let和const支持

目标 ES3 和 ES5 支持 ES6 letconst声明。

常量

const MAX = 100; ++MAX; // Error: The operand of an increment or decrement // operator cannot be a constant.

块的范围

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 支持

TypeScript 1.5 增加了对 ES6 / ES5 阵列上......循环的支持,以及在定位 ES6 时完全支持 Iterator 接口。

示例

当针对这些版本时,TypeScript 编译器会将阵列转换为惯用的 ES3 / ES5 JavaScript:

for (var v of expr) { }

将被排放为:

for (var _i = 0, _a = expr; _i < _a.length; _i++) { var v = _a[_i]; }

装饰

TypeScript 装饰器基于 ES7 装饰器建议

一个装饰者是:

  • 一种表达

  • 评估为一个函数

  • 将目标,名称和属性描述符作为参数

  • 同时可选地返回一个属性描述符以安装在目标对象上

有关更多信息,请参阅装饰者建议。

示例

C类上安装 Decorator readonly 及将enumerable(false)应用于method属性。这允许装饰器更改实现,并且在这种情况下,将描述符扩充为可写:false 和 enumerable:false。

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; } }

计算属性

使用动态属性初始化对象可能有点负担。以下面的例子:

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,我们可以让编译器完成繁重的工作:

function makeNode(name: string, initialNeighbor: Node): Node { return { name: name, neighbors: { [initialNeighbor.name]: initialNeighbor } } }

支持UMD和System模块输出

除了AMDCommonJS模块装载机,打字稿现在支持发光模块UMD通用模块定义)和System模块的格式。

用法

tsc –module umd

tsc –module system

Unicode 码点在字符串中转义

ES6 引入了转义,允许用户仅使用一次转义来表示 Unicode 代码点。

作为一个例子,考虑需要转义一个包含字符'?'的字符串。在 UTF-16 / UCS2 中,'?' 被表示为一个代理对,这意味着它是利用一对的值的16位的代码单元,具体地编码0xD8420xDFB7。以前这意味着你必须按照代码转义"\uD842\uDFB7"。这有一个主要的缺点,很难从代理对中辨别出两个独立的角色。

使用 ES6的代码点转义,您可以用一次转义干净地表示字符串和模板字符串中的确切字符:"\u{20bb7}"。TypeScript 将在 ES3 / ES5 中发出字符串"\uD842\uDFB7"

在 ES3 / ES5 中标记模板字符串

在 TypeScript 1.4 中,我们添加了对所有目标的模板字符串的支持,并为 ES6 添加了标记模板。

当瞄准 ES3 / ES5 时,下面的代码

function oddRawStrings(strs: TemplateStringsArray, n1, n2) { return strs.raw.filter((raw, index) => index % 2 === 1 } oddRawStrings `Hello \n${123} \t ${456}\n world`

将被排放为

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 path="x" />通知编译器关于需要在结果模块的 require 调用中注入的非 TS 模块依赖性; 但是,在 TS 代码中无法使用此模块。

amd-dependency name属性允许为 amd 依赖项传递一个可选名称:

/// <amd-dependency path="legacy/moduleA" name="moduleA"/> declare var moduleA:MyType moduleA.callStuff()

生成的 JS 代码:

define(["require", "exports", "legacy/moduleA"], function (require, exports, moduleA) { moduleA.callStuff() }

通过 tsconfig.json项目支持

在目录中添加tsconfig.json文件表明该目录是 TypeScript 项目的根目录。tsconfig.json 文件指定编译项目所需的根文件和编译器选项。一个项目按以下方式编译:

  • 通过在没有输入文件的情况下调用 tsc,在这种情况下,编译器搜索当前目录中开始的 tsconfig.json 文件并继续父目录链。

  • 通过调用没有输入文件的 tsc 和一个指定包含 tsconfig.json 文件的目录路径的 -project(或者只是 -p)命令行选项。

示例

{ "compilerOptions": { "module": "commonjs", "noImplicitAny": true, "sourceMap": true, } }

有关更多详细信息,请参阅 tsconfig.json wiki页面

--rootDir 命令行选项

选项--outDir重复输出中的输入层次结构。编译器将输入文件的根计算为所有输入文件的最长公共路径; 然后使用它来复制输出中的所有子结构。

有时这是不可取的,例如输入FolderA\FolderB\1.tsFolderA\FolderB\2.ts会导致输出结构镜像FolderA\FolderB\。现在,如果将新文件FolderA\3.ts添加到输入中,则输出结构将弹出以进行镜像FolderA\

--rootDir 指定要在输出中镜像的输入目录而不是计算它。

--noEmitHelpers 命令行选项

TypeSript 编译器会__extends在需要时发出一些帮助器。助手会在每个引用的文件中发出。如果要将所有助手合并到一个位置,或者覆盖默认行为,请使用--noEmitHelpers来指示编译器不要发出它们。

--newLine 命令行选项

默认情况下,输出新行字符是\r\n基于 Windows 的系统和\n基于 *nix 的系统。--newLine命令行标志允许覆盖此行为并指定要在生成的输出文件中使用的新行字符。

--inlineSourceMap和inlineSources命令行选项

--inlineSourceMap导致源映射文件被内联写入生成的.js文件而不是独立.js.map文件。--inlineSources允许额外将源.ts文件内联到.js文件中。