原创 石小石Orz 2025-05-20 08:30 重庆
点击关注公众号,“技术干货”及时达!
点击关注公众号,“技术干货” 及时达!
背景简介
大家好,我是石小石!
在前端项目开发中,我们常常会遇到这样一种情况:「项目中引入了某个第三方库,但它没有提供内置的 TypeScript 类型声明」。此时,如果你在 TypeScript 项目中直接使用这个库,编译器就会报错。
shims-vue.d.ts
中通过 declare 声明此模块,来解决报错。但你是否想过这些问题:
.shims-vue.d.ts
文件中写一个 declare 声明就能解决报错?.d.ts 文件明明没有显示引入,为什么就生效了?
任意 xxx.d.ts 文件声明为什么都能发挥作用吗?
declare module 'xxx'
就让 TypeScript 编译器 “闭嘴”,看似简单,背后却隐藏着 TypeScript 类型系统的一些核心机制。.d.ts
文件的作用
.d.ts
文件是 TypeScript 世界中的 “翻译器”,它不负责运行代码,而是负责「描述代码的结构、类型、接口、模块」,使得 TypeScript 编译器 “明白” 你在干什么,从而让类型检查、提示、自动补全等功能得以正常运作。「为 JavaScript 代码或第三方库补充类型」
.d.ts
文件,手动声明它的类型:// types/jquery.d.tsdeclare var $: any;
「为非代码资源声明模块(如 SVG、CSS、JSON 等)」
在项目中引入非代码资源时,TypeScript 默认是无法识别的,比如:
import logo from './logo.svg';
.d.ts
文件来告诉 TS 这是什么类型:// types/shims-svg.d.tsdeclare module '*.svg' { const content: string; export default content;}
「定义全局变量或类型」
VITE_APP_VERSION
是在构建时注入的变量,你可以这样声明:// types/global.d.tsdeclare const VITE_APP_VERSION: string;
这样就可以在任何文件中使用,不报错、还能获得类型提示。
「定义环境变量、全局命名空间等复杂类型结构」
例如:
interface Window { myGlobalAPI: () => void;}declare namespace MyLib { type Options = { debug: boolean; };}
「补充已有模块的类型信息(模块扩展)」
你可以给已有模块添加自定义类型,不需要修改原始库代码:
// types/vue-router.d.tsimport 'vue-router';declare module 'vue-router' { interface RouteMeta { auth?: boolean; }}
为什么写一个 declare
就能解决报错?
TypeScript 是强类型语言,它在编译时会尝试为每一个变量、函数、模块、类型标识符 “找到定义”。当我们引入一个没有类型声明的第三方模块时,比如:
import something from 'vs-tree';
vs-tree
没有提供.d.ts
文件(也就是没有类型定义),TypeScript 编译器就会报错:但当你写上:
// shims-vue.d.ts 或任何 .d.ts 文件declare module 'vs-tree';
any
类型处理。这其实是使用.d.ts
的一个最基础场景:「模块声明补全」。为什么 .d.ts
文件不引入也能生效?
这要从 TypeScript 的文件识别机制说起。
tsconfig.json
,它会根据其中的配置项决定:要包含哪些文件
要排除哪些文件
要使用哪些类型库(如 DOM、ESNext)
要如何解析模块路径(如路径别名)
.d.ts
文件能自动生效,主要有以下几种情况:在 tsconfig.json
的 include
范围内
.d.ts
文件路径在include
的匹配范围内,TS 编译器就会自动加载它:{ "include": ["src", "types"]}
shims-vue.d.ts
放在src/
或types/
下,它就会自动生效。被编译器当作 “全局声明” 文件识别
.d.ts
文件中如果没有import
/export
,就会被 TypeScript 当作 “全局类型声明文件”(Global Declaration File),自动合并进全局作用域。这种文件中的内容对所有文件可见:// types/global.d.tsdeclare const __APP_VERSION__: string;
__APP_VERSION__
,不需要任何引入。被放置在默认类型目录下(如 @types
)
node_modules/@types
中找类型定义(社区维护的 DefinitelyTyped 类型库)。如果你把声明文件放进这个路径,甚至可以模拟 npm 包类型的形式存在。任意 xxx.d.ts
文件都能生效吗?
include
中被包含,编译器才会自动加载。xx.d.ts
才会被自动加载。但以下情况,即使在 include 中声明也不会被加载。失败原因 | 解释 |
---|---|
使用了模块语法(如 import /export )导致该文件不再是全局声明 | 编译器不会自动把它合并为全局作用域 |
语法错误 | 编译器会跳过整个文件 |
关注更多AI编程资讯请去AI Coding专区:https://juejin.cn/aicoding
点击"阅读原文"了解详情~