You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Types for Service Workers should be built into the default definitions for TypeScript. There are some good examples out there of Service Worker typings from the community.
I think it's necessary to add service worker typings into built-in definitions, though it's still a work-in-progress API.
When I tried to add /// <reference no-default-lib="true"/> directive into service_worker_api to exclude the default lib (like that in lib.webworker.d.ts), I got tons of type missing errors like:
error TS2304: Cannot find name 'Function'.
So instead I have to use
interfaceWindowextendsServiceWorkerGlobalScope{}
to attach interfaces onto self.
This brings some other problems, eg. I must change the incompatible properties like onmessage into what they are on Window interface:
Therefore, I think it would be much better to include service worker typings in default definitions, or, at least there should be a way to make no-default-lib directive act like the built-in ones.
Reacted by barinbritva, val1991 and Roman Orlowski
Anyone know how I can force TS to change the type of self??
first you need --lib webworker to include the webworker library definition. self is defined as declare var self: WorkerGlobalScope;. so update the declaration of WorkerGlobalScope to get what you want.
I really don't like this type of comments, but... Any updates here? I mean, this is just a definition file with a proper compiler flag, isn't it? Maybe we won't be writing service workers in Typescript, but Typescript definitions are really important now days in Javascript development, for me at least. :P.
Reacted by Michael Leonard, Colin Bradley, Objektwerks, electrovir and Albert Mañosa
It's intended to be included by a triple slash directive in the service worker, and registration scripts. It works well for me using the webworker lib along with es5+. Hope this helps
I feel like I'm completely missing something. I tried a couple of the type definition files and they're pretty much missing everything I need. addEventListener isn't declared to take a callback that takes a ServiceWorkerMessageEvent. And ServiceWorkerMessageEvent doesn't have the properties I'm using (request, waitUntil, respondWith). self is missing everything since it's still defined as a WorkerGlobalScope.
And to further add to my confusion this says that the dom lib now has service worker stuff: https://www.npmjs.com/package/@types/service_worker_api Why would that be? I didn't think there was a DOM inside service workers. Also, I tried it and it didn't work.
Is there something else I need to configure or include somewhere?
Pending an update on this, I've just switched my service worker code into vanilla JS. Though types would be great for development, this is a basic failing of TypeScript currently.
preamble, together with declare const self: ServiceWorkerGlobalScope;, seems to do the trick but unfortunately due to #19978 it breaks other sibling modules that do run in DOM context.
It would be an imperfect a good solution otherwise, with the added benefit of disabling the DOM or other libs that would have no effect in service worker context.
I plan to try addressing this later by having multiple sub-projects with dedicated tsconfig.json files, though that would somewhat complicate build process and it’s unclear whether it’ll even work.
Gugustinette (@Gugustinette) solution worked for me to get self.onconnect from SharedWorkerGlobalScope. Why does /// <reference lib="WebWorker" /> work to access SharedWorkerGlobalScope but tsconfig.json's "lib": ["WebWorker"] does not?
Adam McKee (@eighty4) do you have only one tsconfig.json? Do you use it with TSC directly or with some other tooling that respects tsconfig.json (e.g., esbuild, VSC, etc.)? Make sure the tsconfig.json that you think has effect indeed has effect, and you don’t accidentally override something through tsconfig inheritance.
Note that if you share that tsconfig in a project where you also have non-worker code, and you add WebWorker to lib, worker types will apply in non-worker code, which will confuse type validation (e.g., self.onconnect will not raise an error if you use it in your main browser window).
I've since solved it with project references to scope libs to specific code. First time using project references within one webapp and for refs between packages of a monorepo.
I was sad to find that the project references feature can't be hijacked within a bundler built webapp codebase to control the self scope and APIs available for window and worker portions of the app because you would need to add noEmit: false for code that doesn't ever need to be emitted.
Then, use _self in place of self in the ServiceWorker.
This is ugly and skipLibCheck may degrade type accuracy, but I haven't found any other way to support Firefox with this nasty combination of long-running issues.
Is there any progress on this issue? Are developers still doomed to write ServiceWorker code with one eye on the documentation, without the ability to rely on autocompletion and type checking tools?
Reacted by Gugustinette, Kabir Brar and Timothy Totten
This issue will be 10 years old in a few months! Service Workers are used extensively, and yet they still aren't supported properly by TypeScript (and in turn the JS language server in VSCode). The various workarounds are ridiculous and lead to ugly code that is much more difficult to maintain.
So is this just a matter of nobody bothering to do it? Like if someone forked the code, added a 'serviceworker' lib definition separate from 'webworker', and then submitted a pull request, would it actually get merged?
Activity
mhegazy commentedon Oct 21, 2016
Since service workers run in their own context, i suppose we need
--lib serviceworker(similar to--lib webworker).Zhengbo Li (@zhengbli) can we update our declaration files to pull in serviceworker spec idl as well
dolphin-wood commentedon Jan 1, 2017
I think it's necessary to add service worker typings into built-in definitions, though it's still a work-in-progress API.
When I tried to add
/// <reference no-default-lib="true"/>directive into service_worker_api to exclude the default lib (like that inlib.webworker.d.ts), I got tons of type missing errors like:So instead I have to use
to attach interfaces onto
self.This brings some other problems, eg. I must change the incompatible properties like
onmessageinto what they are onWindowinterface:Therefore, I think it would be much better to include service worker typings in default definitions, or, at least there should be a way to make
no-default-libdirective act like the built-in ones.code-tree commentedon Jan 19, 2017
interface Window extends ServiceWorkerGlobalScope {}isn't even working for me.Anyone know how I can force TS to change the type of
self??mhegazy commentedon Jan 25, 2017
first you need
--lib webworkerto include the webworker library definition.selfis defined asdeclare var self: WorkerGlobalScope;. so update the declaration ofWorkerGlobalScopeto get what you want.rektide commentedon Jun 16, 2017
I can't vouch for it, but scouting about it looks like this gist is updating pretty regularly. May be a good candidate for TS to adopt?
michaeljota commentedon Mar 13, 2018
I really don't like this type of comments, but... Any updates here? I mean, this is just a definition file with a proper compiler flag, isn't it? Maybe we won't be writing service workers in Typescript, but Typescript definitions are really important now days in Javascript development, for me at least. :P.
mhegazy commentedon Apr 3, 2018
PRs welcomed. the files are generated https://github.com/Microsoft/TSJS-lib-generator. I would be happy to help if someone wants to pick this issue up.
tiernan commentedon Apr 13, 2018
I wrote an updated gist from the one linked above by rektide here: Service Worker Typings to Supplement lib.webworker.d.ts.
It's intended to be included by a triple slash directive in the service worker, and registration scripts. It works well for me using the webworker lib along with es5+. Hope this helps
caseyhoward commentedon Nov 2, 2018
I feel like I'm completely missing something. I tried a couple of the type definition files and they're pretty much missing everything I need. addEventListener isn't declared to take a callback that takes a ServiceWorkerMessageEvent. And ServiceWorkerMessageEvent doesn't have the properties I'm using (request, waitUntil, respondWith). self is missing everything since it's still defined as a WorkerGlobalScope.
And to further add to my confusion this says that the dom lib now has service worker stuff: https://www.npmjs.com/package/@types/service_worker_api Why would that be? I didn't think there was a DOM inside service workers. Also, I tried it and it didn't work.
Is there something else I need to configure or include somewhere?
jhpratt commentedon Dec 3, 2018
Pending an update on this, I've just switched my service worker code into vanilla JS. Though types would be great for development, this is a basic failing of TypeScript currently.
shqld commentedon Dec 23, 2018
I'm addressing the issue like this. Currently works well.
https://gist.github.com/shqld/32df51a4a4ed429f2c76e4e2cfdf6f96#gistcomment-2793376
22 remaining items
alexbruno commentedon Jan 3, 2023
The simplest solution that worked for me, is just this on the Service Worker code:
F2 commentedon Feb 26, 2023
To avoid aliasing
self, this seems to work in the latest version of TypeScript:ShafSpecs commentedon Mar 28, 2023
It gives an error:
Cannot redeclare block-scoped variable 'self'Using this instead worked:
Yep, it's getting weirder 😆
icazemier commentedon Mar 29, 2023
This works for me (for now... 🤷🏻 ):
tsconfig:
{ "compilerOptions": { "allowJs": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "strictNullChecks": true, "useUnknownInCatchVariables": false, "lib": ["WebWorker", "ESNext"], "noEmit": true, "strict": true, "outDir": "./public/sw", "module": "esnext", "target": "esnext", "incremental": false, "sourceMap": true, "isolatedModules": false, "moduleResolution": "node", "resolveJsonModule": true }, "include": ["service-worker.ts"], "exclude": ["node_modules"] }noel-schenk commentedon Mar 26, 2024
Ivo Cazemier (@icazemier) ty :) adding to tsconfig.json:
"lib": ["WebWorker", ...],did it for me
strogonoff commentedon Sep 30, 2024
Somehow
libdoesn’t work for me, but Ivo Cazemier (@icazemier)’spreamble, together with
declare const self: ServiceWorkerGlobalScope;, seems to do the trick but unfortunately due to #19978 it breaks other sibling modules that do run in DOM context.It would be an imperfect a good solution otherwise, with the added benefit of disabling the DOM or other libs that would have no effect in service worker context.
I plan to try addressing this later by having multiple sub-projects with dedicated
tsconfig.jsonfiles, though that would somewhat complicate build process and it’s unclear whether it’ll even work.hatem-amer commentedon Oct 30, 2024
If you are using Vite (@vitejs), this works for me
Gugustinette commentedon Dec 22, 2024
I got it working with this at the top of my worker code
arianvp commentedon Apr 9, 2025
It seems typings are missing for
InstallEventand thus there are no types for https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes
eighty4 commentedon Aug 8, 2025
Gugustinette (@Gugustinette) solution worked for me to get
self.onconnectfrom SharedWorkerGlobalScope. Why does/// <reference lib="WebWorker" />work to access SharedWorkerGlobalScope but tsconfig.json's"lib": ["WebWorker"]does not?self.onconnectwith the tsconfig.json lib specified becomes an error if I remove the reference comment. So confused!strogonoff commentedon Aug 11, 2025
Adam McKee (@eighty4) do you have only one tsconfig.json? Do you use it with TSC directly or with some other tooling that respects tsconfig.json (e.g., esbuild, VSC, etc.)? Make sure the tsconfig.json that you think has effect indeed has effect, and you don’t accidentally override something through tsconfig inheritance.
Note that if you share that tsconfig in a project where you also have non-worker code, and you add WebWorker to
lib, worker types will apply in non-worker code, which will confuse type validation (e.g., self.onconnect will not raise an error if you use it in your main browser window).eighty4 commentedon Sep 1, 2025
I've since solved it with project references to scope libs to specific code. First time using project references within one webapp and for refs between packages of a monorepo.
I was sad to find that the project references feature can't be hijacked within a bundler built webapp codebase to control the self scope and APIs available for window and worker portions of the app because you would need to add
noEmit: falsefor code that doesn't ever need to be emitted.FusillyCode commentedon Oct 7, 2025
Abdur-Rahman (@ShafSpecs) and Gugustinette (@Gugustinette) solutions break Firefox compatibility because this issue breaks any ServiceWorker scripts that are use
exportorimport. Here is what worked for me:In the tsconfig file, add:
In the ServiceWorker script, add:
Then, use
_selfin place ofselfin the ServiceWorker.This is ugly and
skipLibCheckmay degrade type accuracy, but I haven't found any other way to support Firefox with this nasty combination of long-running issues.vadimmos commentedon Apr 7, 2026
Is there any progress on this issue? Are developers still doomed to write ServiceWorker code with one eye on the documentation, without the ability to rely on autocompletion and type checking tools?
supernovus commentedon May 14, 2026
This issue will be 10 years old in a few months! Service Workers are used extensively, and yet they still aren't supported properly by TypeScript (and in turn the JS language server in VSCode). The various workarounds are ridiculous and lead to ugly code that is much more difficult to maintain.
So is this just a matter of nobody bothering to do it? Like if someone forked the code, added a 'serviceworker' lib definition separate from 'webworker', and then submitted a pull request, would it actually get merged?