声明语法
declare var
声明全局变量declare function
声明全局方法declare class
声明全局类declare enum
声明全局枚举类型declare namespace
声明全局对象interface
和type
声明全局类型export
导出变量export namespace
导出(含子属性的)对象export default
ES6 默认导出export =
commonjs 导出模块export as namespace
UMD 库声明全局变量declare global
扩展全局变量declare module
扩展模块/// <reference />
三斜线指令
声明语句
如果我们想使用第三方库jQuery,常见的方式是通过<script>
标签引入,然后全局使用$
或jQuery
$("#id")
jQuery("#id")
但在ts中,编译器并不能识别$
或jQuery
; 所以我们需要先定义它的类型
declare var jQuery: (selector:string) => any;
// 然后就可使用了
jQuery("#id")
declare var
并没有真正意义上定义一个变量,只是定义了全局变量类型,仅会用于编译时的检查,在编译结果中会被删除。
声明语句只能定义类型,不能定义具体的实现
声明文件
通常把声明语句放到一个单独的文件中(如jQuery.d.ts)中,这就是声明文件
// src/types/jQuery.d.ts
declare var jQuery: (selector: string) => any;
声明文件必须以.d.ts
为后缀
tips: 一般来说,ts会解析项目中所有的.ts
文件和.d.ts
文件;加入无法解析,可以检查tsconfig.json
文件中的files
、include
和exclude
配置,确保其包含了对应的声明文件。
第三方声明文件
一般第三方插件的声明文件不需要我们单独定义,社区已帮我们定义好了:DefinitelyTyped 可直接下载使用。更推荐的是使用@types
统一管理第三方库声明文件
npm install @types/node @types/react @types/jQuery --save-dev
书写声明文件
当一个第三方库没有提供声明文件时,我们就需要自己书写声明文件了。
库的使用场景主要有以下几种:
- 全局变量:通过
<script>
标签引入的第三方库,注入全局变量 - npm包: 通过
import foo from 'foo'
导入,符合ES6模块规范 - UMD库:即可通过
<script>
标签引入,有课通过import
导入 - 直接扩展全局变量:通过
<script>
标签引入后,改变一个全局变量的结构 - 在npm包或UMD库中扩展全局变量:引入npm包或umd库后,改变一个全局变量的结构
- 模块插件:通过
<script>
或import
导入后,改变另一个模块的结构
1. 全局变量
全局变量是最简单的一种场景。
使用全局变量的声明文件时,如果以npm install @types/** --save-dev
安装的,则不需任何配置
全局变量的声明文件主要有以下几种语法:
1. declare var // 声明全局变量
declare const jQuery: (selector: string) => any;
2. declare function //声明全局方法, 同时支持函数的重载
declare function jQuery(selector: string) : any;
declare function jQuery(domReadyCallback: ()=> any): any;
3. declare class //声明全局类
declare class Animal {
name: string;
constructor(name: string);
sayHi(): string;
}
let cat = new Animal('Tom')
4. declare enum //声明全局枚举类型
declare enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
5. declare namespace //声明(含子属性的)全局对象 (推荐使用ES6的模块化方案,不建议使用)
declare namespace jQuery {
function ajax(url: string, settings?: any): void;
const version: number;
}
6. interface 和 type //声明全局类型
interface AjaxSetting {
method?: 'GET' | 'POST';
data?: any;
}
tips: 暴露在最外层的interface
或type
会最为全局类型作用于整个项目中,我们应尽可能的减少全局变量或全局类型的数量。故最好将他们放到namespace
下
declare namespace jQuery {
interface AjaxSetting {
method?: 'GET' | 'POST';
data?: any;
}
function ajax(url: string, setting?: AjaxSetting): void;
}
// 使用
let setting: jQuery.AjaxSetting = {
method: 'POST',
data: { name: 'foo' }
}
jQuery.ajax('/api/post_something', setting)
2. npm包
在尝试给一个npm包创建声明文件之前,需先看该包的声明文件是否已存在。一般npm包的声明文件可能存在于两个地方:
- 与该npm包绑定在一起。依据:
package.json
中有types
字段,或者有一个index.d.ts
声明文件。最为推荐 - 发布到
@types
里。尝试安装一下对应的@types
包就知道是否存在该声明文件了npm install @types/foo --save-dev
如以上两种方式都没找到对应的声明文件,则需我们自己为它写声明文件了。两种方案:
- 创建一个
node_modules/@types/foo/index.d.ts
文件,存放模块声明文件。(代码未保存到仓库中,无法回溯版本,不建议) - 创建一个typs目录,专门用来管理自己写的声明文件,配置
tsconfig.json
中的paths
和baseUrl
字段
tsconfig.json文件内容: