声明文件简介

声明文件是 TypeScript 类型系统的核心组成部分,用于描述 JavaScript 代码的类型结构。理解声明文件有助于更好地使用 TypeScript 开发项目。

声明文件的本质

声明文件只包含类型声明,不包含实现代码。编译后声明文件会被完全移除。

declare function add(a: number, b: number): number

declare const PI: number

declare interface User {
  id: number
  name: string
}

这些声明告诉编译器这些值的类型,但不会生成任何 JavaScript 代码。

declare 关键字

declare 关键字用于声明外部定义的变量、函数、类等。

declare let jQuery: (selector: string) => any

declare function fetch(url: string): Promise<Response>

declare class XMLHttpRequest {
  open(method: string, url: string): void
  send(): void
}

declare 告诉编译器这些声明在运行时存在。

声明文件的扩展名

声明文件使用 .d.ts 扩展名。

src/
  index.ts
  types/
    jquery.d.ts
    lodash.d.ts

TypeScript 会自动识别 .d.ts 文件。

声明文件的类型

声明文件可以声明多种类型:

变量声明

declare const API_URL: string
declare let debug: boolean

函数声明

declare function log(message: string): void
declare function fetch(url: string, options?: RequestInit): Promise<Response>

类声明

declare class User {
  constructor(name: string)
  name: string
  greet(): string
}

接口声明

declare interface Config {
  apiKey: string
  baseUrl?: string
}

类型别名

declare type ID = string | number
declare type EventHandler = (event: Event) => void

枚举声明

declare enum Status {
  Active,
  Inactive,
  Pending
}

模块声明

声明文件可以声明模块。

declare module "lodash" {
  export function chunk<T>(array: T[], size: number): T[][]
  export function debounce<T extends (...args: any[]) => any>(
    func: T,
    wait: number
  ): T
}

导入模块时获得类型支持。

import { chunk, debounce } from "lodash"

const result = chunk([1, 2, 3, 4], 2)
const debouncedFn = debounce(() => {}, 300)

全局声明

声明文件可以定义全局变量。

declare global {
  interface Window {
    myApp: {
      version: string
      config: Record<string, any>
    }
  }
}

window.myApp = {
  version: "1.0.0",
  config: {}
}

全局声明扩展了全局命名空间。

声明文件的位置

声明文件可以放在以下位置:

  1. 项目内的 types 目录
  2. node_modules/@types 目录
  3. 库的根目录
  4. tsconfig.json 指定的位置
{
  "compilerOptions": {
    "typeRoots": ["./types", "./node_modules/@types"]
  }
}

声明文件的作用域

声明文件的作用域取决于声明方式:

  • 全局声明:在所有文件中可用
  • 模块声明:只在导入模块时可用
  • 命名空间声明:在命名空间内可用
declare namespace MyLib {
  interface Options {
    debug: boolean
  }
}

实际应用

声明文件常用于为第三方库添加类型支持。

declare module "analytics" {
  interface Config {
    trackingId: string
    debug?: boolean
  }

  interface Analytics {
    init(config: Config): void
    track(event: string, data?: Record<string, any>): void
    pageview(path: string): void
  }

  const analytics: Analytics
  export default analytics
}

使用时获得完整的类型支持。

import analytics from "analytics"

analytics.init({
  trackingId: "UA-XXXXX-Y",
  debug: true
})

analytics.track("button_click", { button: "submit" })
analytics.pageview("/home")

小结

声明文件使用 .d.ts 扩展名,只包含类型声明。declare 关键字用于声明外部定义的类型。声明文件可以声明变量、函数、类、接口、类型别名、枚举等。声明文件可以定义模块或全局类型。理解声明文件有助于为 JavaScript 代码添加类型支持。