如何在TypeScript中正确定义Window类型

图片

在几乎所有的前端应用中,你都可能遇到过这个错误:

类型'Window & typeof globalThis'上不存在属性'X'。

在这篇文章中,我们将介绍几个不同的解决方案来解决这个问题。


快速修复
 

 Window  接口在名为  lib.dom.d.ts  的文件中全局定义,可以使用各种技术来更改它:

  • 若要在  .ts  或  .tsx  文件中全局更改它,可以使用 declare global 和 interface Window :
     

    图片


     

  • 如果要在  .d.ts  文件中全局更改它,可以指定 interface Window 。
     

    图片


     

  • 要只对一个文件进行更改,可以在  .ts  或  .tsx  文件中使用  declare const window  :
     

    图片



解释
 

接口 Window 在 TypeScript 的全局作用域中,作为 lib.dom.d.ts 中的 DOM 类型的一部分,它描述了浏览器中可用的方法。

当第三方脚本(或者我们自己的代码)向窗口添加一些内容时,问题就出现了:

window.X = Date.now();

这是一个问题,因为 TypeScript 不知道  X  属性,所以当你试图访问它时,它会抛出一个错误:

// @errors: 2339window.X;

因此,我们需要以某种方式改变  Window  的全局定义,以便包含 TypeScript 不知道的新属性。

解决方案1: declare global  在  .ts  或  .tsx  文件中
 

第一个解决方案是使用  declare global  来改变  Window  的全局定义:

图片

这样做有两个原因:首先, declare global  告诉 TypeScript 它里面的任何内容都应该添加到全局作用域中。

第二,我们利用了声明合并,这是 TypeScript 中的一个规则,在相同的作用域中,同名的接口会被合并,所以通过在相同的作用域中重新声明  Window ,我们可以为它附加新的属性。

如果我们使用  type  ,这将不起作用,因为类型不支持声明合并。

// @errors: 2300export {};
// ---cut---
declare global {  type Window = {    X: number;  };}

这个解决方案只在  .ts  或  .tsx  文件中起作用,因为  declare global  只在模块中起作用。因此,就您将定义放在项目中的什么位置而言,这个解决方案有点笨拙。在自己的模块中?与其他东西共存?

解决方案 2:一个  .d.ts  文件
 

一种更整洁的解决方案是在  .d.ts  文件中使用 interface Window

图片

图片

之所以这样做是因为你放在 .d.ts 中的任何内容都会自动进入全局作用域,所以不需要 declare global 。

它还允许您将全局定义放在单独的文件中,这比试图找出应该把它放到哪个  .ts  文件中感觉更干净一些。

解决方案3:单模块覆盖
 

如果你担心在全局作用域中添加类型,你可以使用 declare const window 来重写单个模块中的 window 的类型:

export {};
// ---cut---
declare const window: {  X: number;} & Window;
window.X;//     ^?

declare const window  的作用类似于  const window ,但是在类型级别上,所以它只作用于当前作用域 — 在本例中,是模块,我们声明的类型是当前的  Window  加上新的属性  X 。

如果你需要访问多个文件中的  window.X ,这个解决方案会有点烦人,因为你需要在每个文件中添加  declare const window  行。


我应该使用哪种解决方案?
 

我个人倾向于使用解决方案 2 — 一个  .d.ts  文件,它只有最少的代码行,并且最容易放置在项目中。

我不介意在全局作用域中添加类型。通过实际更改  Window  的类型,您可以更准确地描述代码执行的环境。在我看来,这是额外的好处。

但是如果你真的担心,可以使用  declare const  解决方案。

  欢迎关注公众号:文本魔术,了解更多

  • 51
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值