变量声明空间和类型声明空间
类型声明空间包含用来当做类型注解的内容,但不能作为变量使用。
变量声明空间包含可用作变量的内容,不能作为类型注解。
编译成JS后,会将类型声明空间完全移除。
模块
早期ES6还没出的时候,有 AMD
, CommonJs
。现在按ES6的标准,统一用 import
export
就行。不需要过多考虑别的模块形式。
声明文件
TS中专门用来声明类型的文件,以 d.ts
结尾。
script形式引入的声明文件
例如 jQuery ,引入后会挂载到全局下一个$(jQuery)对象。为了防止命名冲突,我们要利用 declare namespace
。因为限定了所有的类型声明都在jQuery下,所以使用的时候也要 jQuery.xxx
的形式。
declare namespace jQuery {
interface AjaxSettings {
method?: 'GET' | 'POST'
data?: any;
}
function ajax(url: string, settings?: AjaxSettings): void;
}
NPM包的声明文件
npm的三方包如果配备了声明文件,一般会与npm包绑定在一起,查看 package.json
的 types
字段。如果没有绑定,尝试安装 yarn add type/npmpackage -D
,使用者通常会自己写声明文件,发布到 @types
下。
如果以上都没有。自己可以在项目目录里定义一个 types
文件夹,专门存放声明文件。
/path/to/project
├── src
| └── index.ts
├── types
| └── foo
| └── index.d.ts
└── tsconfig.json
这里也要配置下tsconfig的 paths
字段,告诉ts需要解析哪里的。
"compilerOptions": {
"paths": {
"*": ["types/*"]
}
}
扩展全局变量
利用声明合并。没有使用 import
export
就是全局声明。
interface String {
xxx: number
}
利用 declare namespace
给已有的命名空间添加
declare namespace JQuery {
interface CustomOptions {
bar: string;
}
}
扩展npm包的全局变量
写一个自己的声明文件时,可能会用到其他npm包的声明文件,所以我们需要导入 import React from 'react
,导入后,则认为这个声明文件是个模块,再声明的话,都是局部类型声明,此时需要全局声明类型的话,用 declare global
。
import React from 'react'
declare global {
reactEle: React.Element
}
这里我们就可以使用全局的 reactEle
了。
扩充原模块类型
比如 axios
导出的实例,想在它身上挂载 token
以便请求接口时使用。原本实例是不存在 token
属性的。所以:
// 导入原模块的类型
import axios, { AxiosInstance } from 'axios';
// 拓展它。使用interface达到类型合并的效果
declare module 'axios' {
interface AxiosInstance {
token: any;
userId: any;
}
}
// 使用拓展过的实例
import axios from 'axios';
let instance = axios.create({})
instance.token = 'xxx'
instance.userId = 'xxx'
声明文件的依赖
除了 import
来导入其他模块的类型之外,还有 三斜线
指令,使用场景是需要一个全局的类型,你不能使用 import
和 export
关键字,TS会认为是局部声明,需要你导入后才能使用了。
// 引入jquery。这里用的是types=xxx,表示依赖
/// <reference types="jquery" />
// 这里依旧暴露的还是全局类型foo,可以使用使用,不用在使用地 import 它。
declare function foo(options: JQuery.AjaxSettings): string;
// node_modules/@types/jquery/index.d.ts
// sizzle是跟jquery平级的库,是一种依赖
/// <reference types="sizzle" />
// 这里开始用的是path,表示引入文件,并不是依赖
/// <reference path="JQueryStatic.d.ts" />
/// <reference path="JQuery.d.ts" />
/// <reference path="misc.d.ts" />
/// <reference path="legacy.d.ts" />
export = jQuery;