Skip to content

声明文件

声明文件通常指 .d.ts 文件,用来描述值的类型信息,而不提供实际运行时代码。

可以把它理解为“只告诉 TypeScript 这段 API 长什么样,不负责真正实现”。

作用

声明文件主要解决以下问题:

  • 让 TypeScript 理解现有 JavaScript 库的类型
  • 为没有类型信息的全局变量、函数或模块补充定义
  • 给自己编写的库提供类型提示和类型检查能力
  • 让编辑器获得更准确的补全、跳转和报错信息

什么是 .d.ts

.ts 文件既可以写类型,也可以写运行时代码。

.d.ts 文件只用于声明类型,不会被编译成实际 JavaScript 逻辑。

ts
// math.d.ts
declare function add(x: number, y: number): number

这里的 add 只是“声明存在”,并没有真正实现。

什么时候需要声明文件

  • 使用没有自带类型的 JavaScript 库
  • 需要给项目里的全局变量补类型
  • 维护 TS/JS 混合项目
  • 编写要给其他人使用的库

如果一个包已经自带类型,或者已经安装了对应的 @types/*,通常就不需要自己再写一份声明文件。

常见写法

全局声明

适合给全局变量、全局函数或全局接口补类型。

ts
// globals.d.ts
declare const APP_VERSION: string

declare function track(event: string): void

interface Window {
  __APP_NAME__: string
}

这类写法常见于浏览器环境注入变量、构建时常量或脚本标签挂到全局对象上的能力。

模块声明

适合给某个模块名补充类型定义。

ts
// types/math.d.ts
declare module 'math' {
  export function add(x: number, y: number): number
  export function subtract(x: number, y: number): number
}

当代码里执行:

ts
import { add } from 'math'

TypeScript 就可以从这份声明中知道 add 的参数和返回值类型。

为现有库补声明

如果项目中接入了一个没有类型的 JavaScript 文件,也可以单独为它补一份 .d.ts

ts
// my-library.d.ts
declare namespace MyLibrary {
  function doSomething(input: string): void
  function getValue(): number
}

这类写法更常见于历史全局库或非模块化脚本。

常见关键字

声明文件里经常会看到以下关键字:

  • declare:声明某个值或类型存在
  • declare module:声明一个模块
  • declare namespace:声明一个命名空间
  • declare global:扩展全局作用域

例如扩展全局类型时,常见写法如下:

ts
export {}

declare global {
  interface Window {
    __INITIAL_DATA__: {
      userId: string
    }
  }
}

如何接入项目

方式一:让 .d.ts 文件参与编译

只要声明文件位于 tsconfig.jsoninclude 范围内,TypeScript 就会自动读取。

json
{
  "include": ["src", "types"]
}

方式二:配置 typeRoots

如果希望显式指定类型根目录,可以使用 compilerOptions.typeRoots

json
{
  "compilerOptions": {
    "typeRoots": ["./types", "./node_modules/@types"]
  }
}

适合把项目自定义声明和第三方类型来源分开管理。

方式三:配置 types

如果只想启用指定的类型包,可以使用 compilerOptions.types

json
{
  "compilerOptions": {
    "types": ["node", "vite/client"]
  }
}

这会限制自动注入的全局类型范围。

@types/* 的关系

很多第三方包的类型定义由社区维护在 DefinitelyTyped 仓库中,安装后通常以 @types/* 的形式提供。

例如:

bash
npm i -D @types/jquery

安装后,TypeScript 就能识别 jQuery 的类型信息。

优先级上通常是:

  • 包自带类型:直接使用
  • 没有自带类型,但有 @types/*:安装对应类型包
  • 两者都没有:再考虑自己写声明文件

和三斜线指令的关系

声明文件负责“定义类型内容”。

三斜线指令负责“告诉编译器去额外加载哪些类型信息”。

简单理解:

  • .d.ts:定义类型本身
  • /// <reference ... />:补充编译器的读取入口

现代项目里,通常优先用:

  • tsconfig.json
  • include
  • types
  • 正常的模块导入

只有在文件级补充或历史代码场景下,才更常用三斜线指令。

注意事项

  • 声明文件不应该写真实业务实现
  • 全局声明要谨慎,避免污染命名空间
  • 能写成模块类型时,优先写成模块,不要滥用全局声明
  • 自定义声明与第三方声明最好按目录分开管理

参阅

基于 MIT 许可发布