Как правильно инициализировать свойство класса, учитывая, что его значение будет назначено динамически позже? - PullRequest
0 голосов
/ 19 апреля 2020

Ниже приведен класс компонента Vue с прослушивателями событий, которые могут в определенный момент получить экземпляр сервисного работника и сохранить его в свойстве registration.

Проблема, с которой я сталкиваюсь, заключается в том, что даже делать:

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

TypeScript сообщает, что this.registration - это TS2571: Object is of type 'unknown'., что имеет смысл из-за: private registration: unknown

Я был бы очень признателен, если бы кто-то мог предложить, какой правильный способ свойства инициализации и доступа, которые могут быть определены позже?

PS: Фактический тип registration равен ServiceWorkerRegistration

Реализация класса:

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"
  ]
}

1 Ответ

1 голос
/ 19 апреля 2020

Поскольку registration не инициализируется при создании экземпляра, это может быть undefined.

Вы можете пометить его как необязательно :

private registration?: ServiceWorkerRegistration

Или явно указать, что это может быть undefined:

private registration: ServiceWorkerRegistration | undefined

Использование оператора ненулевого утверждения на самом деле является плохой идеей , поскольку он позволяет получить доступ к this.registration свойствам без проверки, определен ли он / инициализирован или нет.

...