TypeScript细碎知识点:三斜杠指令
上一篇介绍 namespace
多文件拆分的内容时,用到了一个三斜杠指令
/// <reference path="xxx" />。
这组指令有多个,其作用分别有所不同。
一、前言
三斜杠指令是包含一个XML
单标签的单行三斜杠注释,注释的内容可被编译器识别,用来指示编译器在编译的过程中包含其它文件,或者用作规定文件输出顺序的方法。
⚠️ 注意事项
使用三斜杠指令时需要注意:只有出现在文件的开头才有效,否则将被当作没有特殊意义的普通注释。这意味着,在三斜杠指令之前,只能有单行或多行注释的存在,当然也可以有其它的三斜杠指令,而不能有其它的语句或者声明。
二、/// <reference path="..." />
这是最常用的指令了,用来声明文件之间的依赖关系。
1. 预处理输入文件
编译器将所有的三斜杠指令通过预处理传递输入文件的方式来解析,在此过程中,其它的文件会被添加到编译中。这个过程会从一系列根文件,即通过命令行或者tsconfig.json
中指定的文件,按照指定的顺序开始开始。在文件被添加到处理列表之前,会按三斜杠指令在文件中出现的顺序,遵循深度优先的的方式来进行解析。如果三斜杠指令使用了相对路径,则是相对于包含文件的路径。
⏰ math.d.ts
// math.d.ts declare namespace MathUtils { function add(a: number, b: number): number; function subtract(a: number, b: number): number; }
⏰ utils.d.ts
/// <reference path="math.d.ts" /> // utils.d.ts declare namespace MyUtils { function calculateTotal(numbers: number[]): number { return numbers.reduce(MathUtils.add, 0); } }
2. 错误使用
以下做法会导致错误:
- 使用三斜杠指令来引入不存在的文件 (我们一般不会故意这么做,因此往往是路径不对);
- 使用三斜杠指令来引入自身(自己引用自己,无限循环)。
3. 使用 --noResolve
标志
如果我们在命令行或者tsconfig.json
中启用了noResolve
,则三斜杠指令不会被解析,此时它们和普通的注释无异,不会产生任何特殊作用。因此,如果发现三斜杠指令不报错也不生效,可以试着检查tsconfig.json
中的相应配置。
{ "compilerOptions": { "noResolve": true // " /// <reference path="..." /> " 将不被解析 } }
三、/// <reference types="..." />
🔊:与
/// <reference path="..." />
指令相似,/// <reference types="..." />
用来声明对包的依赖。
TS对这些包名的解析也和对使用import
语句的解析差不多,因此三斜杠指令也可以视为声明包的导入的一种简单方法。
例如,当我们在文件开头使用了 /// <reference types="node" />
时,node
包和声明文件就会被包含到编译中。
该指令往往在手动编写.d.ts
文件时才需要使用。而在编译过程中,编译器会自动为我们添加 /// <reference types="..." />
,当且仅当生成文件使用了来自引用包的声明时,才会在该文件中加入 /// <reference types="..." />
。
四、/// <reference lib="..." />
🔊:该指令让文件显示包含现有的内置库,基本上,依然是给声明文件的作者使用的。内置
lib
文件的引用方式与在tsconfig.json
中的lib
配置项一致 (例如应该写lib="es2015"
,而不是lib="lib.es2015.d.ts"
)。
例如,在某个文件中使用指令/// <reference lib="es2017.string" />
,等效于在命令行添加--lib es2017.string
标志。
/// <reference lib="es2017.string" /> "foo".padStart(4);
五、/// <reference no-default-lib="true"/>
这个指令会把文件标记为默认库,并高速编译器在编译时不包含默认库。在lib.d.ts
文件及其不同的变体的顶部能看到这个指令。
六、/// <amd-module />
这个指令可以把amd
模块的名称传递给编译器:
// other.ts ///<amd-module name="NamedModule"/> export class C {}
在编译中会把模块名称分配给amd
的define
函数来参与调用:
// ModuleA.js define("ModuleA", ["require", "exports"], function (require, exports) { var C = (function () { function C() {} return C; })(); exports.C = C; });
事实上,除了/// <reference path="..." />
,其它的三斜杠指令大多数人平时都用不上。