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

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

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

// Not SSR friendly
const halfWinHeight = window.innerHeight / 2

// SSR friendly
if (typeof window !== 'undefined') {
  const halfWinHeight = window.innerHeight / 2
}

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

declare const window: {} | undefined

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

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

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

【问题讨论】:

    标签: typescript vue.js nuxt.js server-side-rendering


    【解决方案1】:

    一种可能的解决方案:

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

      // tsconfig.json
      {
        "compilerOptions": {
          "lib": ["dom"]
        }
      }
      
    2. 创建导出window 的实用程序文件,键入为typeof window | undefined

      // @/utils/window.ts
      export default window as typeof window | undefined
      
    3. 在所有使用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 可以用 SSR 未定义这一事实的问题。如果我不导入它不会引发错误,这是毫无意义的,因为如果我忘记导入它,这很可能意味着我也忘记处理 window 可能未定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 2019-12-04
    • 1970-01-01
    • 2010-11-25
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多