变量声明空间和类型声明空间

类型声明空间包含用来当做类型注解的内容,但不能作为变量使用。
变量声明空间包含可用作变量的内容,不能作为类型注解。

编译成JS后,会将类型声明空间完全移除。

模块

早期ES6还没出的时候,有 AMD , CommonJs。现在按ES6的标准,统一用 import export 就行。不需要过多考虑别的模块形式。

声明文件

TS中专门用来声明类型的文件,以 d.ts 结尾。

script形式引入的声明文件

例如 jQuery ,引入后会挂载到全局下一个$(jQuery)对象。为了防止命名冲突,我们要利用 declare namespace。因为限定了所有的类型声明都在jQuery下,所以使用的时候也要 jQuery.xxx 的形式。

  1. declare namespace jQuery {
  2. interface AjaxSettings {
  3. method?: 'GET' | 'POST'
  4. data?: any;
  5. }
  6. function ajax(url: string, settings?: AjaxSettings): void;
  7. }

NPM包的声明文件

npm的三方包如果配备了声明文件,一般会与npm包绑定在一起,查看 package.jsontypes 字段。如果没有绑定,尝试安装 yarn add type/npmpackage -D ,使用者通常会自己写声明文件,发布到 @types 下。

如果以上都没有。自己可以在项目目录里定义一个 types 文件夹,专门存放声明文件。

  1. /path/to/project
  2. ├── src
  3. | └── index.ts
  4. ├── types
  5. | └── foo
  6. | └── index.d.ts
  7. └── tsconfig.json

这里也要配置下tsconfig的 paths 字段,告诉ts需要解析哪里的。

  1. "compilerOptions": {
  2. "paths": {
  3. "*": ["types/*"]
  4. }
  5. }

扩展全局变量

利用声明合并。没有使用 import export 就是全局声明。

  1. interface String {
  2. xxx: number
  3. }

利用 declare namespace给已有的命名空间添加

  1. declare namespace JQuery {
  2. interface CustomOptions {
  3. bar: string;
  4. }
  5. }

扩展npm包的全局变量

写一个自己的声明文件时,可能会用到其他npm包的声明文件,所以我们需要导入 import React from 'react ,导入后,则认为这个声明文件是个模块,再声明的话,都是局部类型声明,此时需要全局声明类型的话,用 declare global

  1. import React from 'react'
  2. declare global {
  3. reactEle: React.Element
  4. }

这里我们就可以使用全局的 reactEle 了。

扩充原模块类型

比如 axios 导出的实例,想在它身上挂载 token 以便请求接口时使用。原本实例是不存在 token 属性的。所以:

  1. // 导入原模块的类型
  2. import axios, { AxiosInstance } from 'axios';
  3. // 拓展它。使用interface达到类型合并的效果
  4. declare module 'axios' {
  5. interface AxiosInstance {
  6. token: any;
  7. userId: any;
  8. }
  9. }
  1. // 使用拓展过的实例
  2. import axios from 'axios';
  3. let instance = axios.create({})
  4. instance.token = 'xxx'
  5. instance.userId = 'xxx'

声明文件的依赖

除了 import 来导入其他模块的类型之外,还有 三斜线 指令,使用场景是需要一个全局的类型,你不能使用 importexport 关键字,TS会认为是局部声明,需要你导入后才能使用了。

  1. // 引入jquery。这里用的是types=xxx,表示依赖
  2. /// <reference types="jquery" />
  3. // 这里依旧暴露的还是全局类型foo,可以使用使用,不用在使用地 import 它。
  4. declare function foo(options: JQuery.AjaxSettings): string;
  1. // node_modules/@types/jquery/index.d.ts
  2. // sizzle是跟jquery平级的库,是一种依赖
  3. /// <reference types="sizzle" />
  4. // 这里开始用的是path,表示引入文件,并不是依赖
  5. /// <reference path="JQueryStatic.d.ts" />
  6. /// <reference path="JQuery.d.ts" />
  7. /// <reference path="misc.d.ts" />
  8. /// <reference path="legacy.d.ts" />
  9. export = jQuery;