如何将 DOM 声明为可能未定义

Posted

技术标签:

【中文标题】如何将 DOM 声明为可能未定义【英文标题】:How to declare DOM as possibly undefined 【发布时间】:2021-07-27 20:28:24 【问题描述】:

我和我的同事目前正在monorepo 中使用Nuxt 构建一个新的Vue s-s-r 应用程序。我们有 Nuxt 应用程序作为一个包,另一个是我们的组件库。我们都是 Typescript 的新手,但我们能够毫无问题地设置所有内容。

问题是:组件库应该是 s-s-r 友好的,但不应该知道 Nuxt 本身,所以在访问窗口属性时我宁愿使用if (typeof window !== 'undefined') 而不是if (process.browser)。现在我想知道如果有人尝试访问窗口属性而不首先检查它是否已定义,我是否可以使用 Typescript 和 Eslint 来引发错误。

// Not s-s-r friendly
const halfWinHeight = window.innerHeight / 2

// s-s-r friendly
if (typeof window !== 'undefined') 
  const halfWinHeight = window.innerHeight / 2

我知道如果我使用联合类型,Typescript 会引发错误,例如:

declare const window:  | undefined

然后我收到我想要的错误Object is possibly 'undefined'

显然,我不想声明所有可能的windowdocument 属性,所以我想知道我是否可以使用lib 像DOM,但是一个可能未定义的DOM。棘手的部分是我们只知道是否在运行时定义了窗口,那么我如何为它分配一个值以让 Typescript 在构建时知道?

我正在尝试使用 Typescript 解决这个问题,但这可能不是最好的方法。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

一种可能的解决方案:

    使用dom 库获取window 的类型声明:

    // tsconfig.json
    
      "compilerOptions": 
        "lib": ["dom"]
      
    
    

    创建导出window 的实用程序文件,键入为typeof window | undefined

    // @/utils/window.ts
    export default window as typeof window | undefined
    

    在所有使用window(来自dom)的文件中,将实用程序文件导入为window,以便使用您的自定义类型版本:

    // MyFoo.vue
    import window from '@/utils/window'
    
    export default 
      mounted() 
        window.console.log('hi')  // ❌ Object is possibly 'undefined'
        ^^^^^^
    
        window?.console.log('hi') // ✅
      
    
    

【讨论】:

不错,但它并不能真正解决确保人们不会忘记 window 可以用 s-s-r 未定义这一事实的问题。如果我不导入它不会引发错误,这是毫无意义的,因为如果我忘记导入它,这很可能意味着我也忘记处理 window 可能未定义。

以上是关于如何将 DOM 声明为可能未定义的主要内容,如果未能解决你的问题,请参考以下文章

错误 C2027:使用未定义类型 - 如何声明类

React-router-dom:TypeError:无法读取未定义的属性(读取“位置”)

Sass错误:未定义变量,即使它已声明

即使将'i'声明为全局变量,它仍显示'i'未定义

如何在 JavaScript 中处理“未定义”[重复]

如何在 JavaScript 中处理“未定义”[重复]