使用声明文件
TypeScript 中的 .d.ts
声明文件主要有以下几种来源:
-
TypeScript 语言内置的声明文件。
-
安装的第三方声明文件。
-
自定义的声明文件。
语言内置的声明文件
当我们在计算机中安装了 TypeScript 语言后,同时也安装了一些语言内置的声明文件,它们位于 TypeScript 语言安装目录下的 lib
文件夹中。下面列举了部分内置的声明文件:
lib.d.ts
lib.dom.d.ts
lib.es2015.d.ts
lib.es2016.d.ts
lib.es2017.d.ts
lib.es2018.d.ts
lib.es2019.d.ts
lib.es2020.d.ts
lib.es5.d.ts
lib.es6.d.ts
TypeScript 语言内置的声明文件统一使用 lib.[description].d.ts
命名方式,其中,description
部分描述了该声明文件的内容。在这些声明文件中,既定义了标准的 JavaScript API,如 Array API、Math API 以及 Date API 等,也定义了特定于某种 JavaScript 运行环境的 API,如 DOM API 和 Web Workers API 等。
TypeScript 编译器在编译代码时能够自动加载内置的声明文件。因此,我们可以在代码中直接使用那些标准 API
,而不需要进行特殊的配置。例如,我们可以在代码里直接使用标准的 DOM
方法,TypeScript 能够从内置的声明文件 lib.dom.d.ts
中获取该方法的类型信息并进行类型检查。示例如下:
const button = document.getElementById('btn');
第三方声明文件
如果我们的工程中使用了某个第三方代码库,例如 jQuery
,通常我们也想要安装该代码库的声明文件。这样,TypeScript 编译器就能够对代码进行类型检查,同时代码编辑器也能够根据声明文件中的类型信息来提供代码自动补全等功能。
在尝试安装某个第三方代码库的声明文件时,可能会遇到以下三种情况,下面以 jQuery
为例:
-
在安装
jQuery
时,jQuery
的代码包中已经内置了它的声明文件。 -
在安装
jQuery
时,jQuery
的代码包中没有内置的声明文件,但是在DefinitelyTyped
网站上能够找到jQuery
的声明文件。 -
通过以上方式均找不到
jQuery
的声明文件,需要自定义jQuery
的声明文件。
含有内置声明文件
实际上,在 jQuery
的代码包中没有包含内置的声明文件。本节我们将以 RxJS
代码库为例,在 RxJS
的代码包中内置了 TypeScript 声明文件。RxJS
是一个支持响应式编程的代码库,主要用于处理基于事件的异步数据流。在开始之前需要安装 Node.js
并对工程进行简单的初始化。关于 Node.js
环境配置的详细介绍请参考第 9 章。
假设当前工程目录结构如下:
C:\app
|-- index.ts
|-- package.json
`-- tsconfig.json
在 C:\app
目录下运行 npm
命令来安装 RxJS
,示例如下:
npm install rxjs
在安装后,工程目录结构如下:
C:\app
|-- index.ts
|-- node_modules
| |-- rxjs
| | |-- <省略了部分文件>
| | |-- index.d.ts
| | |-- index.js
| | |-- package.json
| | `-- README.md
| `-- <省略了部分文件>
|-- package.json
`-- tsconfig.json
在 C:\app\node_modules\rxjs
目录中存在一个 index.d.ts
文件,它就是 RxJS
代码库内置的 TypeScript 声明文件。通常来讲,若代码库的安装目录中包含 .d.ts
文件,则说明该代码库提供了内置的声明文件。
在 C:\app\index.ts
中使用 RxJS
时,编译器能够正确地进行类型检查并提供智能提示功能。示例如下:
import { Observable } from 'rxjs';
const observable = new Observable(subscriber => {
subscriber.next(1);
setTimeout(() => {
subscriber.next(2);
subscriber.complete();
}, 1000);
});
observable.subscribe({
next(x) {
console.log('got value ' + x);
},
error(err) {
console.error('something wrong occurred: ' + err);
},
complete() {
console.log('done');
}
});
此例第 1 行,从 rxjs
模块中导入了 Observable
对象,编译器能够自动地从 C:\app\node_modules\rxjs\index.d.ts
文件中读取 Observable
的类型声明。
DefinitelyTyped
DefinitelyTyped
( https://definitelytyped.org/ )是一个公开的集中式的 TypeScript 声明文件代码仓库,该仓库中包含了数千个代码库的声明文件。DefinitelyTyped
托管在 GitHub 网站上,由开源社区和 TypeScript 开发团队共同维护。
如果我们正在使用的第三方代码库没有内置的声明文件,那么可以尝试在 DefinitelyTyped
仓库中搜索声明文件。例如,jQuery
没有内置的声明文件,我们可以前往 DefinitelyTyped
的搜索页面去搜索关键字 jQuery
,如图7-2所示。

因为 DefinitelyTyped
仓库中提供了 jQuery
的声明文件,因此将跳转到 npm
上 jQuery
声明文件主页,即 @types/jquery
代码包。值得一提的是,DefinitelyTyped
仓库中的所有声明文件都会发布到 npm
的 @types
空间下,如图7-3所示。

接下来,让我们安装 jQuery
的声明文件,即 @types/jquery
代码包。在开始之前需要安装 Node.js
并对工程进行简单的初始化。关于 Node.js
环境配置的详细介绍请参考第 9 章。
假设当前工程目录结构如下:
C:\app
|-- index.ts
|-- package.json
`-- tsconfig.json
在 C:\app
目录下使用 npm
命令来安装 @types/jquery
声明文件代码包,如下所示:
npm install @types/jquery
安装后,工程目录结构如下:
C:\app
|-- index.ts
|-- node_modules
| `-- @types
| |-- jquery
| | |-- <省略了部分文件>
| | |-- index.d.ts
| | `-- package.json
| `-- <省略了部分文件>
|-- package.json
|-- package-lock.json
`-- tsconfig.json
jQuery
的声明文件被安装到了 C:\app\node_modules\@types\jquery
目录下,该目录下的 index.d.ts
文件就是 jQuery
的声明文件。
在 C:\app\index.ts
中使用 jQuery API
时,编译器能够从安装的声明中获取 jQuery
的类型信息并正确地进行类型检查。示例如下:
import * as $ from 'jquery';
$('p').show();
typings与types
每个 npm
包都有一个标准的 package.json
文件,该文件描述了当前 npm
包的基础信息。例如,jQuery
包中 package.json
文件的主要内容如下:
{
"name": "jquery",
"description": "JavaScript library for DOM operations",
"version": "4.0.0-pre",
"main": "dist/jquery.js",
"homepage": "https://jquery.com",
"author": {
"name": "JS Foundation and other contributors",
},
"repository": {
"type": "git",
"url": "https://github.com/jquery/jquery.git"
},
"keywords": [
"jquery",
"javascript",
"browser",
"library"
],
"bugs": {
"url": "https://github.com/jquery/jquery/issues"
},
"license": "MIT",
"dependencies": {},
"devDependencies": {},
"scripts": {}
}
该文件中比较重要的属性有表示包名的 name
属性、表示版本号的 version
属性和表示入口脚本的 main
属性等。
TypeScript 扩展了 package.json
文件,增加了 typings
属性和 types
属性。虽然两者的名字不同,但是作用相同,它们都用于指定当前 npm
包提供的声明文件。
假设有如下目录结构的工程:
C:\my-package
|-- index.js
|-- index.d.ts
`-- package.json
package.json
文件的内容如下:
{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"typings": "index.d.ts"
}
此例中,使用 typings
属性定义了 my-package
包的声明文件为 index.d.ts
文件。当 TypeScript 编译器进行模块解析时,将会读取该属性的值并使用指定的 index.d.ts
文件作为声明文件。这里我们也可以将 typings
属性替换为 types
属性,两者是等效的。关于模块解析的详细介绍请参考 7.9 节。
如果一个 npm
包的声明文件为 index.d.ts
且位于 npm
包的根目录下,那么在 package.json
文件中也可以省略 typings
属性和 types
属性,因为编译器在进行模块解析时,若在 package.json
文件中没有找到 typings
属性和 types
属性,则将默认使用名为 index.d.ts
的文件作为声明文件。因此,上例中的 package.json
文件可以修改为如下形式:
{
"name": "my-package",
"version": "1.0.0",
"main": "index.js"
}
typesVersions
每个声明文件都有其兼容的 TypeScript 语言版本。例如,如果一个声明文件中使用了 TypeScript 3.0 才开始支持的 unknown
类型,那么在使用该声明文件时,需要安装 TypeScript 3.0 或以上的版本。也就是说,将该声明文件提供给其他用户使用时,需要使用者安装 TypeScript 3.0 或以上的版本,这可能会给使用者带来困扰。
在 TypeScript 3.1 版本中,编译器能够根据当前安装的 TypeScript 版本来决定使用的声明文件,该功能是通过 package.json
文件中的 typesVersions
属性来实现的。
假设有如下目录结构的工程:
C:\my-package
|-- ts3.1
| `-- index.d.ts
|-- ts3.7
| `-- index.d.ts
|-- index.d.ts
`-- index.js
package.json
文件的内容如下:
{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"typings": "index.d.ts",
"typesVersions": {
">=3.7": {
"*": ["ts3.7/*"]
},
">=3.1": {
"*": ["ts3.1/*"]
}
}
}
此例中,我们定义了两个声明文件匹配规则:
-
第 7 行,当安装了 TypeScript 3.7 及以上版本时,将使用 ts3.7 目录下的声明文件。
-
第 10 行,当安装了 TypeScript 3.1 及以上版本时,将使用 ts3.1 目录下的声明文件。
需要注意的是,typesVersions
中的声明顺序很关键,编译器将从第一个声明(此例中为 ">=3.7")开始尝试匹配,若匹配成功,则应用匹配到的值并退出。因此,若将此例中的两个声明调换位置,则会产生不同的结果。
此外,如果 typesVersions
中不存在匹配的版本,如当前安装的是 TypeScript 2.0 版本,那么编译器将使用 typings
属性和 types
属性中定义的声明文件。
自定义声明文件
如果使用的第三方代码库没有提供内置的声明文件,而且在 DefinitelyTyped
仓库中也没有对应的声明文件,那么就需要开发者自己编写一个声明文件。
在 7.7 节中介绍了如何编写声明文件,但如果我们不想编写一个详尽的声明文件,而只是想要跳过对某个第三方代码库的类型检查,则可以使用下面介绍的方法。
我们还是以 jQuery
为例,只不过不再安装 DefinitelyTyped
提供的 jQuery
声明文件,而是自定义一个 jQuery
声明文件,让编译器不对 jQuery
进行类型检查。
假设当前工程目录结构如下:
C:\app
|-- index.ts
|-- package.json
`-- tsconfig.json
接下来,我们在 C:\app
目录下创建一个 .d.ts
声明文件,例如 jquery.d.ts
。jquery.d.ts
声明文件的内容如下:
declare module 'jquery';
此例中的代码是外部模块声明,该声明会将 jquery
模块的类型设置为 any
类型。
在 C:\app\index.ts
文件中,可以通过如下方式使用 jQuery
声明文件:
import * as $ from 'jquery';
$('p').show();
// ~~~~
// 类型为:any
此例中,jquery
模块中所有成员的类型都成了 any
类型,这等同于不对 jQuery
进行类型检查。