Below is the Vue component class with an event listeners that can receive an instance of service worker at some point of time and save it under registration
property.
The problem I experience is that even doing:
if (this.registration && this.registration.waiting) {
this.registration.waiting.postMessage(SERVICE_WORKER_MESSAGES.skipWaiting)
}
TypeScript communicates that this.registration
is TS2571: Object is of type 'unknown'.
which makes sense because of:
private registration: unknown
I would really appreciate if somebody could suggest what is a proper way of initialising and access properties that can be defined later?
P.S: The actual type of registration
is ServiceWorkerRegistration
Class implementation:
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"
]
}
Since registration
is not initialized when the instance is created it can be undefined
.
You can mark it as optional:
private registration?: ServiceWorkerRegistration
Or explicitly specify that it can be undefined
:
private registration: ServiceWorkerRegistration | undefined
Using non-null assertion operator is actually a bad idea because it will allow accessing this.registration
properties without checking if it is defined/initialized or not.