三斜线指令

三斜线指令是包含单个 XML 标记的单行注释,它们将作为编译指令,影响编译后的 .js 文件的输出内容。

随着模块标准的不断发展,三斜线指令如今已不再适用,无论是从代码管理还是从通用性的角度来说,模块都优于三斜线指令,因此不建议再使用三斜线指令。

但是,在实际项目中,你可能会遇到以往遗留的三斜线指令代码,所以仍需要了解三斜线指令的用法。本节将对三斜线指令做简要介绍。

引用其他文件

要引用其他文件,使用以下三斜线指令,示例代码如下。

/// <reference path ="引用文件路径"/>

假设 a.ts 文件的内容如下。

let a: number = 1;

假设 b.ts 文件的内容如下。

/// <reference path ="a.ts"/>
let b: boolean = true;

当执行 tsc b.ts 命令时,由于 b.ts 文件引用了 a.ts 文件,存在引用关系,因此虽然目标文件只有 b.ts,但编译命令执行时会同时编译 a.tsb.ts 文件,并同时输出 a.jsb.js 文件。

还可以使用 --outFile 选项指定输出文件路径及名称,例如,执行以下命令。

> tsc b.ts –outFile c.js

由于 b.ts 文件通过三斜线指令引用了 a.ts 文件,因此会将 a.ts 文件的代码同时包含在 b.ts 文件中,编译 b.ts 并输出 c.js 文件。c.js 文件的内容如下。

var a = 1;
/// <reference path ="a.ts"/>
var b = true;

指定包含在编译中的库文件

要指定包含在编译中的库文件,使用以下三斜线指令。

/// <reference lib="库名称" />

可选择库名称列表和 tsconfig.json 文件中的 lib 编译选项中可选择的名称列表相同。

例如,ECMAScript 2017 引入了字符串补全长度的功能,如果某个字符串没达到指定长度,会在头部或尾部补全。padStart() 用于头部补全,padEnd() 用于尾部补全。以下代码使用了 padEnd() 方法。如果编译选项中的 modulelib 使用了较早版本的 ECMAScript,则会引起编译错误。

var str: string = "hello";
//错误TS2550: 'string'不存在'padEnd'属性,是否应修改目标库?可尝试更改’lib’编译选项
//为’es2017’或之后的版本
str = str.padEnd(11, " world");
console.log(str);

此时,使用三斜线指令,指明编译该文件时使用的库文件,输出 JavaScript 时将按目标 ECMAScript 版本输出文件内容。

/// <reference lib="es2017.string" />
var str: string = "hello";
str = str.padEnd(11, " world");
console.log(str);

注意事项及其他指令

三斜线指令仅在其所在文件的顶部有效。该指令必须放在其他语句、声明、注释之前,否则将被视为普通单行注释,没有任何效果。示例代码如下。

let a: boolean = true;
/// <reference path ="a.ts"/>
let b: number = 1;

除上述指令之外,还有其他的三斜线指令,它们的应用场景较少,这里仅进行简单介绍。

/// <reference types="..." />

与 /// <reference path="…​" /> 指令相似,/// <reference types="..." /> 指令是用来声明依赖的。 /// <reference types="…​" /> 指令声明了对某个包的依赖。

对这些包的名字的解析与在 import 语句里对模块名的解析类似。可以简单地把三斜线类型引用指令当作 import 声明的包。

例如,把 /// <reference types="node" /> 引入声明文件,表明这个文件使用了 @types/node/index.d.ts 文件里声明的名字,并且这个包需要在编译阶段与声明文件一起包含进来。

/// <reference no-default-lib="true"/>

/// <reference no-default-lib="true"/> 指令把一个文件标记成默认库,通常会在 lib.d.ts 文件和类似文件的顶端看到该指令。

该指令指示编译器不在编译中包含默认库(即 lib.d.ts 文件)。这里的影响类似于在命令行上传递 –noLib

注意,当使用 --skipDefaultLibCheck 编译选项时,编译器将仅忽略检查带 ///<reference no-default-lib="true"/> 的文件。

/// <amd-module />

默认情况下,AMD 模块是匿名生成的。当使用其他工具处理编译后的模块文件时,这会导致问题。

amd-module 指令允许给编译器传入一个可选的模块名,示例 .ts 文件如下。

///<amd-module name='NamedModule'/>
export class C {}

当编译成 .js 文件后,会将 NamedModule 传入 AMD define 函数里,示例代码如下。

define("NamedModule", ["require" "exports"], function (require, exports) {
    var C = (function () {
        function C() {
        }
        return C;
    })();
    exports.C = C;
});

/// <amd-dependency />

/// <amd-dependency /> 指令已经废弃了,请使用 import "moduleName" 语句代替。

/// <amd-dependency path="x" /> 告诉编译器有一个非 TypeScript 模块依赖需要注入,它将作为目标模块 require 调用的一部分。

amd-dependency 指令也可以带一个可选的 name 属性,可以为 amd-dependency 传入一个可选名字,示例 .ts 文件如下。

/// <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()
});