声明文件的作用主要是为没有类型的 js 代码定义类型或者定义全局的类型,声明文件通常以 .d.ts 结尾。

声明语法

主要有以下一些声明语法,多数以 declare 开头,declare 表示只进行声明而没有具体的代码实现。

  • declare var 声明全局变量
  • declare function 声明全局方法
  • declare class 声明全局类
  • declare enum 声明全局枚举类型
  • declare module 扩展模块
  • declare global 扩展全局变量
  • interfacetype 声明全局类型

作为 JS 代码的类型

假设我们存在一个 .js 文件,那么可以使用相同目录下的同名.d.ts 作为类型的补充,当导入并使用

比如存在以下三个文件:

  • math.js
  • math.d.ts
  • main.ts
// math.js

function sum(x, y) {
    return x + y
}
export { sum }
// math.d.ts

declare function sum(x: number, y: number): number
export { sum }
// main.ts

import { sum } from "./math.js"

sum(1, "x") // Argument of type 'string' is not assignable to parameter of type 'number'.

main.ts 的代码中, 虽然 import 的是 math.js 文件,但会自动使用 math.d.ts 声明的类型。

$$tip

通常来说,发布代码时也不会发布 .ts 文件,为了兼容性和减少代码体积,发布的代码都是 .js 文件和 .d.ts 文件。

这样一来,纯 JavaScript 开发环境可以直接引入 .js 文件进行开发,如果是 TypeScript 开发环境搭配 .d.ts 文件也能正常开发。

$$

reference

通过 /// <reference path="./types.d.ts" />/// <reference types="types" /> 可以引入声明。

$$tip

reference 必须写在文件最顶端。

$$

比如存在以下文件:

  • types.d.ts
  • main.ts
// types.d.ts

interface Person {
    name: string
    age: number
}
// main.ts

/// <reference path="./types.d.ts" />

const mingren: Person = {
    name: "鸣人",
    age: 20,
}

declare module

declare module 可以扩展已有的模块声明。

像上一个例子的 math.js 是我们自己编写的代码,那么自然可以再创建一个同目录同名的 math.d.ts 文件补充声明。假如 math 是一个安装的模块,那么它会存在 node_modules 文件夹下,最好的办法是通过 declare module 来补充类型。

比如存在以下文件:

  • node_modules/math/index.js
  • types.d.ts
  • main.ts
// node_modules/math/index.js

function sum(x, y) {
    return x + y
}
export { sum }
// types.d.ts

declare module "math" {
    function sum(x: number, y: number): number
    export { sum }
}
// main.ts

/// <reference path="./types.d.ts" />

import { sum } from "math"

sum(1, "x") // Argument of type 'string' is not assignable to parameter of type 'number'.

我们先是在 types.d.ts 中补充了 math 模块的类型,同时在 main.ts 中引入 types.d.ts 。那么在 main.ts 中使用 sum 时就有类型提示了。