1. /// <reference ... />
/// <reference path="..." />有三个属性,path、types、lib、no-default-lib。
1.1. path
/// <reference path /> 是 TypeScript 早期的模块化方案,用于解决当时 JavaScript 不支持 import/export 的问题。它通常配合outFile使用,通过指定文件路径来声明依赖关系,并控制多个文件合并为一个 JS 文件时的输出顺序。了解更多。
该方式已被 ESModule 完全取代。TypeScript 目前仍支持它,主要是为了兼容老版本或老项目。
使用三斜线指令的文件不能混合使用 import/export 语法,否则指令会失效,被当作普通注释处理。在原生支持 ESModule 的环境中,本就不需要使用指令方式,混用只会造成混乱。
1.2. types
types 属性,在当前模块中引入第三方模块库的类型声明,即标准类型声明@types/<package>。注意默认是索引文件 index,如果不是索引文件则需要指定文件名。
typescript
/// <reference types="node" />
/// <reference types="element-plus/global" />
使用指令的方式引入模块类型属于局部方式,即尽在当前引入模块有效。需要全局生效的话需要在 tsconfig.json 文件中配置。
json
{
// ...
"compilerOptions": {
// ...
"types": ["vite/client"] // 对应 @types/vite/client.d.ts
}
}
1.3. lib
lib 属性用于引入 TypeScript 内置的类型声明库 ,它告诉 TypeScript 编译器,当前代码预期运行在哪种 JavaScript 环境(包括语言标准库版本和宿主 API)。
不同的 JavaScript 环境(如 ES5、ES2020、浏览器 DOM、WebWorker)对应不同的内置类型集合。TypeScript 为这些环境预置了对应的类型声明文件(如 es2020、dom 等)。
需要注意的是,lib 影响的是类型检查时可用的内置类型(如 Promise 、 document ),而不影响编译输出的语法版本(由 target 控制)。
同时,TypeScript 编译环境本身的版本与 JavaScript 版本并非严格一一对应 ,而是通过 lib 选项让编译器"模拟"对某个 JavaScript 环境的类型支持。
在文件中通过 lib 属性,告诉编译环境,使用 es2017 的版本的字符串编译此模块。
typescript
/// <reference lib="es2017.string" />
"foo".padStart(4);
在单文件中,单独通过三斜杠指令引入内置类型的情况不多,一般会在 tsconfig.ts 中配置好,编译器的版本和编译后产物的版本。
json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"lib": [
"ES2020", // Typescript 编译器版本
"DOM", // 浏览器环境 DOM
"DOM.Iterable"
]
}
}
1.4. no-default-lib
此指令将文件标记为默认库。你会在 lib.d.ts 及其不同变体文件的顶部 看到此注释。该指令指示编译器不要在编译中包含默认库(即 lib.d.ts)。其效果类似于在命令行中传递 --noLib 选项。
TypeScript 官方用它来标记自己的内置库文件。
typescript
/// <reference no-default-lib="true" />
interface Array<T> {
// ... 类型定义
}
自定义默认库,也可以覆盖修改 Typescript 内置的库,下面的完全覆盖了内置 Array,现在全局 Array 仅有一个 first 方法。
typescript
// custom-lib.d.ts
/// <reference no-default-lib="true" />
interface Array<T> {
first: () => T // 修改内置的 Array
}
定义完成后,需要在配置文件中指定该文件,这样就可以作为全局默认的库文件了。
json
{
"compilerOptions": {
"lib": [], // 禁用内置库(或省略,因为自定义库会覆盖)
"noLib": false // 保持默认,不需要设为 true
},
"files": [
"custom-lib.d.ts", // 必须放在最前面
"main.ts"
]
}
在 tsconfig.json 中配置,noLib配置项,禁用所有的内置库,会导致所有的类型报错,而指令只对当前文件有效。
json
{
"compilerOptions": {
"noLib": true // 禁用所有内置默认库
}
}
typescript
const arr = [1, 2, 3]; // 找不到名称 'Array'
console.log('hello'); // 找不到名称 'console'
const str = 'hello'; // 找不到名称 'String'(字符串字面量也会报错)
为了提高性能,跳过自定义默认库的类型文件的类型检查,Typescript 中skipDefaultLibCheck。
json
{
"compilerOptions": {
"skipDefaultLibCheck": true, // 跳过检查
},
}
1.5. preserve
preserve="true" 是一个标记,用于防止编译器从输出中移除三斜线指令。
typescript
/// <reference path="./sourcemap.json" preserve="true" />
// 某些构建工具需要这些指令在输出文件中存在
typescript
/// <reference path="../dist/types.d.ts" preserve="true" />
// 输出后仍然保持对类型文件的引用
typescript
/// <reference path="./config.d.ts" preserve="true" />
// 让生成的文件明确标识依赖关系
2. /// <amd-module />
指令用于在编译 AMD 模块时,显式指定模块的名称,解决匿名模块带来的问题。
在 tsconfig.json 的配置文件中 module 配置为amd,即打包后的产物为 amd 的代码格式。
json
{
"compilerOptions": {
"module": "amd", // 必须设置为 AMD
"outFile": "./dist/bundle.js",
"target": "es5"
}
}
默认情况下,编译之后生成的 amd 代码,是匿名的。
typescript
// math.ts
export function add(a: number, b: number) {
return a + b;
}
typescript
// math.js (AMD 格式)
define(["require", "exports"], function(require, exports) {
function add(a, b) {
return a + b;
}
exports.add = add;
});
使用 amd-module 指令指定属性name="math"则编译后的 amd 的代码有了名字 math。
typescript
/// <amd-module name="math" />
export function add(a: number, b: number) {
return a + b;
}
typescript
// math.js (AMD 格式,有名称)
define("math", ["require", "exports"], function(require, exports) {
function add(a, b) {
return a + b;
}
exports.add = add;
});
3. /// <amd-dependency />
该指令已弃用。现使用 import "moduleName"; 语句取代。是对///<amd-module />的的增强,该指令可以指定依赖模块。
typescript
/// <amd-dependency path="legacy/moduleA" name="moduleA"/>
declare var moduleA: MyType;
moduleA.callStuff();
typescript
define(["require", "exports", "legacy/moduleA"], function (
require,
exports,
moduleA
) {
moduleA.callStuff();
});
4. 忽略三斜线指令
使用选线 --noResolve 参数编译文件,则会忽略三斜杠指令,即三斜杠指令不再生效。或者在 tsconfig.json 配置文件中配置选项参数。noResolve 默认是 false,即启用三斜杠指令。
typescript
// utils.ts
export function log(msg: string) {
console.log(msg);
}
// main.ts
/// <reference path="./utils.ts" />
log("Hello"); // 使用 utils.ts 中的函数
通过 tsc 编译 选项参数 --noResolve 关闭 (忽略) 三斜杠指令。
bash
# 编译成功,bundle.js 包含 utils.ts 的内容
tsc main.ts --outFile bundle.js
tsc main.ts --outFile bundle.js --noResolve
# 编译失败!因为找不到 log 函数(utils.ts 没有被包含)
同时,也可以通过 tsconfig 配置文件全局关闭三斜杠指令。noResolve=true,即关闭三斜杠指令。
json
{
"compilerOptions": {
"noResolve": true // 关闭
}
}
5. outFile 如何配合 /// <reference path />

编译器会对输入文件进行预处理 ,按照以下规则处理:从根文件开始(命令行指定的文件或tsconfig.json中的files列表),按根文件指定的顺序进行预处理,遇到 ///<reference path /> 指令时,将其目标文件加入编译,以深度优先 的方式,按指令在文件中的出现顺序解析。最终,文件会按照预处理后的输入顺序 输出到 outFile 指定的单一文件中。
outFile只有在module设置为amd、system或none时才生效。如果设置为commonjs或 es2015,会报错或忽略此选项。
json
{
"compilerOptions": {
"module": "amd", // 必须为 'amd'、'system' 或 'none'
"target": "es5",
"outFile": "./dist/bundle.js" // 合并输出的单一文件
},
"files": [
"./src/main.ts" // 入口文件,会递归处理其中的 reference 指令
]
}
files明确指定顺序
json
{
"compilerOptions": {
"module": "none",
"outFile": "./dist/app.js"
},
"files": [
"./src/utils.ts", // 先输出
"./src/models.ts", // 再输出
"./src/main.ts" // 最后输出(依赖前两个)
]
}
在文件中使用三斜线指令声明依赖,编译器会按指令顺序处理依赖。
typescript
// main.ts
/// <reference path="./utils.ts" />
/// <reference path="./models.ts" />
// 代码中使用 utils 和 models 的内容
在现代开发中,这个方案已被打包工具(Webpack、Rollup、Vite)配合 ESModule 所取代。但如果需要维护老项目,理解这个机制仍然很有必要。