TypeScript中导出declare类型时为何允许重声明块级作用域变量?
TypeScript同名声明有无export的差异原理
基础规则前置
- TS 文件有两种作用域模式:
- 全局脚本:文件内无任何
import/export关键字,所有顶级声明默认挂载到全局作用域,会和全局内置声明、其他全局脚本的声明共享作用域,重名就会触发冲突。 - 模块:只要文件内存在
import/export关键字,TS 自动将其识别为模块,所有顶级声明默认属于模块局部作用域,不会和全局声明直接冲突。
- 全局脚本:文件内无任何
- TS 内部有两套独立的命名空间:类型命名空间和值命名空间,同一个标识符可以同时作为类型和值存在,二者互不干扰。
无export时报错的原因
你的第一个示例没有 export,属于全局脚本:
- 大部分前端项目的 TS 配置都会引入 DOM 类型库,全局作用域本身已经内置了
Element值声明(对应 DOM 元素的构造函数)。 - 你写的
declare const Element: {two: string}属于全局值命名空间的声明,和内置的全局Element值重名,因此触发「不能重声明块级变量」的报错。
补充:你写的declare type Element属于全局类型命名空间,只会和全局内置的Element接口发生声明合并,本身不会导致报错,你误以为的「自己的两个声明冲突」是错觉,真正的冲突来源是值声明和全局内置声明重名。
加export后无报错的原因
当你给类型声明加上 export 后,文件被识别为模块,所有声明都在模块局部作用域内:
export declare type Element是模块导出的类型,属于模块的类型命名空间。declare const Element是模块局部的值声明,属于模块的值命名空间,二者分属不同命名空间,天然不会冲突。- 模块局部声明的优先级高于全局声明,局部的
Element值会覆盖全局内置的Element,不会触发重名冲突。
内容的提问来源于stack exchange,提问作者Xen_mar
相关产品推荐
相关产品推荐

