前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库TypeScript d.ts 声明文件与实现文件的区别
TyTypeScript类型工程

TypeScript 的 .d.ts 声明文件负责什么,为什么不能代替实现?

声明文件告诉编译器某个值应该怎样使用,值本身仍要由真正的运行环境提供。

前端进阶之旅 · 一题精讲更新于 2026.09.06
TypeScript#类型工程#类型系统
先看核心答案读代码示例
理解线索

同一份 API 的两个方面

  1. 实现代码执行计算、读取状态并产生真实结果
  2. 声明文件描述调用方式与可用成员
  3. 消费代码依据声明接受检查,运行时调用实际实现

下面假设包确实具备相同的具名函数导出;只创建这个声明文件不会生成对应 JavaScript。

核心回答

先记住这个答案

.d.ts 文件描述已有模块或全局环境的公开类型,例如函数参数、返回值、类成员和对象结构,让 TypeScript 在没有实现源码时也能检查调用。它不会实现函数、安装依赖、创建全局变量或校验运行时数据。声明可以随 JavaScript 包提供,也可以由类型包或项目自己的补充文件提供。维护声明时必须对照实际导出方式和行为,不能为了消除报错而编造不存在的成员;对自己用 TypeScript 编写的库,通常优先从实现生成公开声明,减少人工双写的偏差。

  • 声明提供编译期契约,运行时值来自真实实现
  • 参数和导出形式必须与实际库保持一致
  • 手写声明适合补充缺失契约,不能用来修复运行时错误

没有源码也可以检查调用是否合理

消费者安装一个 JavaScript 工具包时,编译器未必分析包内全部实现。公开声明可以给出稳定边界,例如解析函数接收字符串,成功后返回带名称和标识的对象。调用者因此能获得参数检查、自动补全和返回值信息。

下面声明一个具名函数和它的返回接口。它没有函数体,不能解释内部如何解析,也没有承诺任何字符串都一定成功。是否抛错、是否接受空白、字段如何归一化仍需要真实实现与 API 文档明确,并由相应测试验证。

声明公开函数签名而不编写函数体TypeScript
// index.d.ts
export interface ParsedUser {
  id: number;
  name: string;
}
export declare function parseUser(text: string): ParsedUser;

消费者可以按 ParsedUser 使用返回值,但这些类型在运行时不会自动校验 JSON。若 JavaScript 实现返回错误字段,声明不会替它修正;若实现没有该导出,运行时仍然会失败。

先确认缺的是类型还是实际模块

报错找不到模块时,可能是包未安装、路径错误、exports 限制或类型缺失。只有最后一类才适合通过补声明解决。给根本不存在的包写环境模块声明,可能让类型检查安静下来,却把问题推迟到打包或启动时。

如果包已有官方类型,应先核对实际版本和模块解析配置;第三方类型包也需要与运行库匹配。旧声明可能漏掉新参数,新声明也可能承诺旧运行库没有的 API。不要把编辑器提示出现当作整个依赖安装与运行链路已经正确。

选择生成声明还是维护手写契约

自己的 TypeScript 库通常通过 declaration 从实现生成 .d.ts,让参数修改可以同步进入公开产物。但自动生成仍可能暴露不稳定内部类型,需要审查最终声明与消费测试。生成文件并不自动意味着设计出了合适的公共 API。

为无类型 JavaScript 库补声明时,可以先覆盖实际使用到的可靠接口,再逐步扩展。每个重载和可选字段都应该有行为依据;不确定输入可以保留 unknown 并在边界解析,不必一开始就用宽 any 宣称所有调用都合法。

回答前,多想一步

容易答错的地方

声明了函数就能直接在运行时调用它
声明文件不会产生实现或加载脚本;消费者仍需要正确安装、导入或初始化真实模块,缺少运行时值时调用照样失败。
为了编译通过可以把返回值写成理想结构
声明应描述事实,错误承诺会让调用者在静态检查通过后遇到缺字段或错误类型;应修复实现、解析边界或声明本身。
试着用自己的话回答

面试官还会怎么问?

声明文件能包含接口和类型别名吗?

可以,它们用于描述公开契约和辅助类型;但声明中出现的运行时值必须在其他地方真实存在,不能依靠类型声明创建对象。

什么时候不需要自己写 .d.ts?

库已经提供匹配的类型,或自己的实现可以可靠生成声明时,通常直接使用现有产物;只有确实缺失或需要扩展契约时再补充。

给返回值写了精确类型还需要运行时解析吗?

对于外部数据仍需要。类型检查假设声明可信,网络响应和用户输入不会因为函数签名精确就自动符合这个结构。

从一道题,走向一组知识

把知识连起来

类型工程

为什么输入的 .d.ts 不会被 tsc 编译成 JavaScript,也不会自动复制到 dist?

理解声明输入为什么不会变成 JavaScript 产物

类型工程

怎样用 declare module 为没有类型的 JavaScript 包补声明?

给确实存在但没有类型的模块补充契约

参考资料

  • TypeScript:Type Declarations
  • TypeScript:Declaration Files Introduction

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 没有源码也可以检查调用是否合理
  3. 先确认缺的是类型还是实际模块
  4. 选择生成声明还是维护手写契约
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑