本文详解在TypeScript中访问服务器端传递的全局数据时的类型错误处理。介绍了使用any类型断言、declare var声明以及接口声明合并三种方法,并重点说明了在ES模块中通过declare global增强Window接口的最佳实践,确保类型安全与代码可维护性。
在某些场景下,开发者需要在 TypeScript 项目中引入自定义的全局变量。例如,在构建 Web 应用时,常需将服务端渲染阶段生成的属性传递给浏览器端的 JavaScript 代码。通常的做法是在内联脚本中定义一个名为 __INITIAL_DATA__ 的全局变量,并将其赋值为一个经过 JSON 序列化的对象:
<script>
window.__INITIAL_DATA__ = {
userID: "536891193569405430",
};
</script>此时,若在 TypeScript 文件中直接尝试访问 window.__INITIAL_DATA__ ,编译器会抛出类型错误,原因是它无法识别 __INITIAL_DATA__ 属性的定义。
// Property '__INITIAL_DATA__' does not exist
// on type 'Window & typeof globalThis'
const initialData = window.__INITIAL_DATA__;下文将介绍几种让 TypeScript 识别 window.__INITIAL_DATA__ 属性存在的方法,从而消除编译器的类型报错。
使用类型断言
解决此类类型错误最快捷的方式是利用 any 类型进行类型断言。通过将 window 对象强制转换为任意类型,即可访问其 __INITIAL_DATA__ 属性:
const initialData = (window as any).__INITIAL_DATA__;该方案能消除类型错误。若需临时访问 TypeScript 未定义类型的 window 对象属性,这是一种简便的解决手段。
由于 (window as any).__INITIAL_DATA__ 表达式的类型为任意类型,因此 initialData 也继承为任意类型。我们可以进一步使用类型断言,为 initialData 变量指定更具体的类型定义:
type InitialData = {
userID: string;
};
const initialData = (window as any).__INITIAL_DATA__ as InitialData;此后,即可以类型安全的方式访问 initialData.userID :
const userID = initialData.userID; // string 类型 需注意,此方式并不保证 window.__INITIAL_DATA__ 在运行时一定被正确赋值。类型检查器会信任开发者的断言,因此开发者需自行确保赋值给 window.__INITIAL_DATA__ 的对象结构符合预期。
声明一个全局变量
另一种方案是使用 declare var 语法来声明全局变量。这使得 TypeScript 能够识别具有指定名称和类型的全局变量:
declare var __INITIAL_DATA__: InitialData; 现在,我们可以直接访问 __INITIAL_DATA__ 变量……
const initialData = __INITIAL_DATA__; ……或者通过 window 对象来获取:
const initialData = window.__INITIAL_DATA__; 需注意的是,在 ECMAScript 模块内部通过 declare var 声明的变量,无法通过 window.__INITIAL_DATA__ 形式访问,否则将收到类型错误。所谓 ECMAScript 模块,指的是包含顶级 import 或 export 声明的文件。
可以使用 declare global { ... } 语法在全局作用域中声明全局变量,从而允许在 JavaScript 模块内部或外部文件中通过 window.__INITIAL_DATA__ 和 __INITIAL_DATA__ 两种形式进行访问。
export function someExportedFunction() {
// ...
}
declare global {
var __INITIAL_DATA__: InitialData;
}
const initialData = window.__INITIAL_DATA__;若需在多个文件或模块中访问 window.__INITIAL_DATA__ ,建议在项目中创建一个 globals.d.ts 文件,并在其中声明所有需要使用的全局变量:
declare var __INITIAL_DATA__: InitialData; 增强 Window 接口
最后,可以利用 TypeScript 的接口声明合并机制,告知编译器在 Window 类型上存在名为 __INITIAL_DATA__ 的属性。为此,需定义一个名为 Window 的接口,并设置 __INITIAL_DATA__ 属性:
interface Window {
__INITIAL_DATA__: InitialData;
}TypeScript 会将上述接口定义与 lib.dom.d.ts 中定义的 Window 接口进行合并,生成单一的 Window 类型。如此一来,下方的赋值操作便不再产生类型错误:
const initialData = window.__INITIAL_DATA__; 同样地,此方法在 ECMAScript 模块中亦无法直接生效。为使 window.__INITIAL_DATA__ 表达式能正确通过类型检查,仍需借助 declare global { ... } 语法:
export function someExportedFunction() {
// ...
}
declare global {
interface Window {
__INITIAL_DATA__: InitialData;
}
}
const initialData = window.__INITIAL_DATA__;以上即为详解如何在TypeScript中声明全局变量的详细内容,更多关于TypeScript声明全局变量的资料请关注本站其它相关文章!