跳到主要内容

什么是 declare 关键字?

下文默认基于 TypeScript 5.x。

面试速答(30 秒版 TL;DR)

  • declare 的作用是:告诉 TypeScript“这个东西在运行时会存在,但实现不在当前文件里”
  • 它主要用于类型声明,而不是写运行时逻辑。
  • 常见场景:
    • .d.ts 声明文件;
    • 给第三方 JS 库补类型;
    • 声明全局变量、全局函数、模块、命名空间;
    • 扩展 windowglobalThis 等全局对象类型。
  • 一句话记忆:
    • declare 负责“告诉编译器有这回事”;
    • 不负责“真的创建这个值”。

1. 为什么需要 declare

TypeScript 做类型检查时,只能根据它“看得见”的声明来判断。

但工程里经常会遇到这类情况:

  • 运行时脚本已经往全局挂了变量;
  • 第三方 JS 包能用,但没类型;
  • 某个对象由宿主环境提供,比如浏览器、Node、打包器注入值。

这时如果没有类型声明,TS 就不知道它的存在。

2. 最简单的例子:声明一个全局变量

declare const APP_VERSION: string;

console.log(APP_VERSION);

它的含义是:

  • 编译器可以把 APP_VERSION 当成 string 看;
  • 但这行代码不会在运行时创建变量。

所以如果真实环境里没有这个值,运行时照样会报错。

3. declare 最常见的宿主:.d.ts 文件

例如:

declare module "legacy-sdk" {
export function init(token: string): void;
export function request(path: string): Promise<unknown>;
}

这类文件的定位就是:

  • 不写实现;
  • 只写类型契约;
  • 让 TypeScript 知道怎么检查你的调用代码。

4. 声明全局对象扩展也是高频题

例如给 window 补一个字段:

declare global {
interface Window {
__APP_CONFIG__: {
apiBase: string;
env: "dev" | "prod";
};
}
}

然后你就可以:

window.__APP_CONFIG__.apiBase;

这类写法在:

  • 老项目接全局脚本;
  • SSR 注水数据;
  • 微前端主子应用通信;

都很常见。

5. declare 能声明哪些东西

常见包括:

  • declare const
  • declare let
  • declare function
  • declare class
  • declare namespace
  • declare module
  • declare global

例如:

declare function track(eventName: string, payload?: Record<string, unknown>): void;
declare class Player {
play(): void;
pause(): void;
}

6. declare 和真正实现的区别

看下面两段代码:

declare function sum(a: number, b: number): number;
function sum(a: number, b: number) {
return a + b;
}

区别在于:

  • 第一段只有声明,没有实现;
  • 第二段既给类型,也给运行时代码。

所以 declare 很像在说:

  • “你先相信运行时会有这个东西,我这里只补类型信息。”

7. 高频面试题标准答法

7.1 declare 会不会生成 JavaScript 代码

通常不会。

它的核心用途就是类型声明,不是生成实现。

7.2 declareas 有什么区别

  • declare:给某个符号补“外部存在”的类型声明;
  • as:对某个已有值做类型断言。

一个偏“声明符号”,一个偏“断言值”。

7.3 为什么第三方库经常有 .d.ts

因为很多库需要把“可被外部消费的 API 结构”暴露给 TypeScript 用户,而不需要把源码细节都暴露出来。

8. 常见误区

  • 误区 1:以为 declare 会创建变量或函数。
    • 不会,它只告诉编译器。
  • 误区 2:觉得写了 declare 就绝对安全。
    • 如果运行时没有实现,依然会崩。
  • 误区 3:把 declare 当成“任何缺类型问题的万能药”。
    • 声明写错了,本质上是在欺骗编译器。

速记要点

  • declare = 声明运行时存在、当前文件不实现的符号。
  • 典型场景是 .d.ts、第三方库补类型、全局变量扩展。
  • 它只影响编译期,不负责生成运行时实现。