三斜线指令

状态: 初稿

三斜线指令是一条包含单个 XML 标签的单行注释.
注释内容可以改变编译器的工作方式.

一条有效的三斜线指令应放置在所属文件最上方.
只有单行或多行注释, 或其他三斜线指令能位于一条三斜线指令之前.
跟随任一语句或声明的三斜线指令被视作常规单行注释, 没有特殊含义.

/// <reference path="..." />

/// <reference path="..." /> 指令是该组最常用的一条.
它将作为文件间依赖的声明.

三斜线 reference 指示编译器在编译过程中包含额外文件.

它也服务于 --out--outFile, 作为调整输出顺序的方法.
文件按预处理轮后输入的相同顺序输出到目标位置.

预处理输入文件

编译器对输入文件执行预处理轮解析所有三斜线 reference 指令.
在这个过程中, 额外文件被添加进编译.

该过程从一组根文件开始;
它们由命令行或 tsconfig.json 文件中的 "files" 列表指定.
预处理器按列入顺序处理这些根文件.
一个文件在加入编译前, 它所有三斜线 reference 指令都已处理, 它们的目标已被包含.
预处理器按文件中出现先后顺序以深度优先方式解析所有三斜线 reference 指令.

对非根文件, 三斜线 reference 指令解析出的路径相对于所属文件.

错误举例

引用一个不存在的文件是错误的.
一个文件用三斜线 reference 引用自身是错误的.

使用 --noResolve

如果指定了编译器选项 --noResolve, 所有三斜线 reference 都会被忽略; 它们既不导致添加新文件, 也不会改变供给文件顺序.

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

与作为依赖声明的 /// <reference path="..." /> 指令相似, /// <reference types="..." /> 指令声明包上的依赖.

解析这些包名的过程类似解析 import 语句中模块名的过程.
可简单地把三斜线 reference-types 指令看作声明包的 import.

例如, 在一个声明文件包含 /// <reference types="node" /> 声明这个文件使用来自 @types/node/index.d.ts 的标识符.
所以, 这个包应该与该声明文件一并包含于编译中.

仅当你手写 d.ts 文件时才使用这些指令.

对编译过程中生成的声明文件, 编译器自动为你插入 /// <reference types="..." />;
一条 /// <reference types="..." /> 被插入到生成的声明文件当且仅当结果文件使用了来自被引用包的任一声明.

而要在 .ts 文件中声明一个 @types 包上的依赖, 可通过命令行或 tsconfig.json 文件中的 --types 选项.
阅读 using @types, typeRoots and types in tsconfig.json files (在 tscofnig.json 文件使用 @types, typeRoots, types) 获得更多信息.

/// <reference lib="..." />

这条指令允许显式包含一个现有的内建 lib 文件.

内建 lib 文件按 tsconfig.json"lib" 编译器选项 (例如: 使用 lib="es2015", 而非 lib="lib.es2015.d.ts", 等等.) 相同的方式引用.

有些声明文件作者依赖内建类型, 如 DOM APIs 或 内建 JS run-time 构造器如 SymbolIterable,
推荐使用三斜线 reference-lib 指令. 以前这些 .d.ts 文件需要添加那些类型的 forward/duplicate 指令.

举个例子, 添加 /// <reference lib="es2017.string" /> 到一个编译中的文件等同于以 --lib es2017.string 选项编译.

1
2
3
/// <reference lib="es2017.string" />

"foo".padStart(4);

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

这条指令标记一个文件为默认库.
你会在 lib.d.ts 文件最上方看到这条注释及其变体.

这条指令指示编译器不要在编译中包含默认库(即 lib.d.st).
它的影响相当于在命令行传递 --noLib 选项.

还要注意, 如果你传递 --skipDefaultLibCheck, 编译器只会跳过对含有 /// <reference no-default-lib="true"/> 的文件的检查.

/// <amd-module />

一般说来, AMD 模块是匿名生成的.
如果使用其他工具处理生成的模块, 如打包器 r.js, 可能会引发问题.

amd-module 指令允许向编译器传递可选的模块名:

amdModule.ts
1
2
3
///<amd-module name="NamedModule"/>
export class C {
}

它会导致作为调用 AMD define 的一部分给模块指定模块名 NamedModule:

amdModule.js
1
2
3
4
5
6
7
8
define("NamedModule", ["require", "exports"], function (require, exports) {
var C = (function () {
function C() {
}
return C;
})();
exports.C = C;
});

/// <amd-dependency />

: 这条指令已废弃. 使用 import "moduleName"; 语句作为替代.

/// <amd-dependency path="x" /> 通知编译器需要注入到结果模块 require 调用的关于一个非 TS 模块的依赖信息.

amd-dependency 指令也有可选的 name 属性; 允许为 amd-dependency 传递可选名字:

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

生成的 JS 代码:

1
2
3
define(["require", "exports", "legacy/moduleA"], function (require, exports, moduleA) {
moduleA.callStuff()
});
如果这篇文章对您有用,可以考虑打赏:)