考虑到稍后将动态分配它的值,如何正确初始化 class 的 属性?

How to properly initialise property of the class considering that it's value will be assigned later dynamically?

下面是带有事件侦听器的 Vue 组件 class,它可以在某个时间点接收 service worker 的实例并将其保存在 registration 属性.

我遇到的问题是即使这样做:

if (this.registration && this.registration.waiting) {
  this.registration.waiting.postMessage(SERVICE_WORKER_MESSAGES.skipWaiting)
}

TypeScript 表示 this.registrationTS2571: Object is of type 'unknown'.,这是有道理的,因为: private registration: unknown

如果有人可以建议什么是初始化和访问可以稍后定义的属性的正确方法,我将不胜感激?

P.S:registration的实际类型是ServiceWorkerRegistration

Class 实施:

export default class Core extends Vue {
  private refreshing = false
  private updateExists = false
  private registration: unknown

  updateApp (): void {
    this.updateExists = false

    // this.registration --> TS2571: Object is of type 'unknown'.
    if (this.registration && this.registration.waiting) {
      //                     ~~~~~~~~~~~~~~~~~  

      // this.registration --> TS2571: Object is of type 'unknown'.
      this.registration.waiting.postMessage(SERVICE_WORKER_MESSAGES.skipWaiting)
      // ~~~~~~~~~~~~~~
    }
  }

  addEventListeners () {
    document.addEventListener(SERVICE_WORKER_EVENTS.updated, ((event: CustomEvent) => {
      this.registration = event.detail /* store the ServiceWorkerRegistration instance for later use. */
      this.updateExists = true
    }) as EventListener,
    { once: true })
  }

  created () {
    this.addEventListeners()

    /*
    Refresh all open app tabs when a new service worker is installed */
    navigator.serviceWorker.addEventListener(`controllerchange`, () => {
      if (!this.refreshing) {
        this.refreshing = true
        window.location.reload()
      }
    })
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "sourceMap": true,
    "noImplicitThis": true,
    "baseUrl": ".",
    "types": [
      "webpack-env",
      "jest"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

由于在创建实例时未初始化 registration,因此可以是 undefined

你可以标记为optional:

private registration?: ServiceWorkerRegistration

或者明确指定可以是undefined:

private registration: ServiceWorkerRegistration | undefined

使用非空断言运算符实际上是一个 坏主意,因为它允许访问 this.registration 属性而不检查它是否为 defined/initialized。