1. 什么是 TS 声明文件
在 TypeScript 中以 .d.ts
为后缀的文件,称为 TypeScript 声明文件。它的作用是描述 JavaScript 模块内所有导出接口的类型信息。
2. 什么时候需要写 TS 声明文件
在使用 TypeScript 开发的项目中,常常需要引入公共模块,或者第三方库。如果这些公共模块或第三方库是用 JS 写的,那么 TS 就无法检测到类型信息,在编译阶段会报错。
这时候有人会说,能不能将这些公共模块或第三方库的代码用 TS 重写呢?答案是不行,因为重写之后,使用这些库的 JS 项目就不兼容了,这些项目不能执行 TS 代码。
那么有没有一种方式,既可以让这些类库支持 TS ,又能兼容 JS 项目呢?有的,就是使用 TS 声明文件。例如我们有一个 index.js
文件,在同级目录下有一个 index.d.ts
声明文件:
- common
|- index.js
|- index.d.ts
当 TS 项目中引入了 index.js
模块,TS 默认会去同级目录下找同名的声明文件,这样 JS 模块就能具有类型了。而 JS 项目引入 index.js
模块,则会忽略这个声明文件。
在日常开发中,很多情况下我们不需要单独去编写 TS 声明文件。例如我们使用 TS 编写一个 npm 包,只要在编译的时候让 TS 自动生成声明文件,并在发布的时候将 .d.ts
文件一起发布即可。
但以下几种情况还是需要手动定义声明文件:
-
通过
script
标签引入的第三方库一些通过 CDN 引入的工具包(例如 jQuery),挂载了一些全局方法,如果在 TS 中直接使用的话,编译阶段会报错,这个时候就要对这些全局方法进行 TS 声明。
-
使用第三方 npm 包,但是没有提供声明文件
第三方 npm 包如果有提供声明文件的话,一般会以两种形式存在:一是
@types/xxx
,二是在源码中提供.d.ts
声明文件。第一种一般是使用率比较高的库会提供,可以通过npm i @types/xxx
尝试安装。如果这两种都不存在的话,就需要我们自己来定义了。 -
项目中使用 JS 编写的公共模块
本人现在做的项目,里面大部分是 JS 编写的,少数组件开始使用 TS 开发,对于一些公共模块,就必须手动添加声明文件,否则编译阶段就会报错了。
3. 如何编写 TS 声明文件
不同形式的声明文件,写法上有一定差异。还要注意,声明文件只是对类型的定义,不能进行赋值。
全局变量
全部变量的声明主要有以下几种语法:
declare let/const // 声明全局变量
declare function // 声明全局方法
declare class // 声明全局类
declare enum // 声明全局枚举类型
declare namespace // 声明(含有子属性的)全局对象
interface/type // 声明全局类型,declare 可以不需要
这里需要注意的是只是定义类型,不能进行赋值。
// 变量
declare let userName: string;
declare const wx: any;
// 函数,函数重载
declare function getName(uid: number): string;
declare function getName(): string;
declare function getName(cb: () => any): any;
// 类
declare class Course {
cid: number;
constructor(cid){};
getCoursePrice(): number;
}
// 枚举
declare enum Status {
Loading,
Success,
Failed,
}
// 接口,declare 可以不需要
interface CourseInfo {
cid: number;
name: string;
}
interface CGIData<T> {
data: T;
retcode: 0;
}
// 命名空间
declare namespace User {
// 局部 Test.User
interface User {
name: string;
age: number;
}
function getUserInfo(name: string): User {
return "";
}
namespace fn {
function extend(obj: any): any;
}
}
// 声明合并
declare function User(id: number): string;
npm 包
对于没有提供声明文件的 npm 包,我们可以创建一个 types 目录,来管理自己写的声明文件,同时需要在配置文件 tsconfig.json
中的 path 和 baseUrl 中配置:
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": "./", // types文件夹的相对路径
"paths": { "*": ["types/*"]}
}
}
npm 包的声明文件主要有以下几种写法:
export const/let // 导出变量
export namespace // 导出(含有自属性的)对象
export default // ES6 默认导出
export = // commonjs 导出模块
拓展原有模块/全局变量
对于已经有声明定义的模块或者全局变量,可以利用 TS 中的声明合并对其进行拓展。
例如在 window 下挂载的一些全局变量:
interface Window {
readonly request?: any;
readonly devToolsExtension?: any;
readonly wx?: any;
}
对已有模块进行拓展:
declare module "querystring" {
function escape(str: string): string;
function unescape(str: string): string;
}
还可以使用三斜线指令对声明文件进行引用:
/// <reference path=”custom.d.ts" />
4. 如何让 TS 在编译时自动生成 .d.ts
文件
只需要在 tsconfig.json
配置文件中开启即可,TS 编译时就会自动生成 .d.ts
声明文件:
{
"compilerOptions": {
"declaration": true
}
}