TypeScript: Unable to access ServiceWorkerGlobalScope via `self.`
Since ServiceWorker
related types sit in lib.webworker.d.ts
, webworker
lib need to be added to tsconfig.json
.
{
"compilerOptions": {
"lib": [
"es2017",
"webworker"
]
}
}
But in current lib.webworker.d.ts
, it declare var self: WorkerGlobalScope;
, so we can’t access ServiceWorkerGlobalScope via self.
TypeScript Version: 2.2.1
Expected behavior:
Can access ServiceWorkerGlobalScope via self.
(like self.clients
)
Actual behavior:
Access with error.
About this issue
- Original URL
- State: open
- Created 7 years ago
- Reactions: 53
- Comments: 35 (5 by maintainers)
Commits related to this issue
- proper typings for self in service workers is an open issue https://github.com/Microsoft/TypeScript/issues/14877#issuecomment-402743582 the workaround is to turn service-worker/index.ts into a modul... — committed to fictitious/typescript-worker-example by carpet-bot 5 years ago
- Service Worker TS! Rewrote the Service Worker in TypeScript! It *kind of* works great, but not quite. I wish the TypeScript team made tooling for Workers a bit better, as it seems harder to work with... — committed to Offroaders123/Smart-Text-Editor by Offroaders123 2 years ago
- sample-system-web-app: Migrate worker files to typescript This CL does a couple of things: 1. Moves the worker script into its own ts_library because it needs a different tsconfig.json than the r... — committed to chromium/chromium by deleted user a year ago
- Moving from Better-TypeScript I really like that library, but I think I only want to use in in places I fully have to. Now that my Service Worker is implemented in full plain TS, rather than JSDoc JS... — committed to Offroaders123/Dovetail by Offroaders123 5 months ago
Here is what worked for me:
tsconfig.json
:Not sure why the empty import is required 🤷♂️
It feels like TypeScript needs to break the various worker types apart in its definitions. This isn’t just a service worker issue, it’s an issue for other contexts that have a different global, like shared workers & the various worklets.
Either that, or there should be a way to declare which interface is the global.
The various
self
hacks in this thread only work for references toself
. You’ve still got incorrect types for the global.Adding
declare var self: ServiceWorkerGlobalScope;
on top of my service worker implementation fixes thatPiecing together several comments in here, this is all I ended up needing:
webworker
lib in tsconfig:self
and export null in service worker file:I found multiple config files and installing npm packages not necessary (or even helpful).
Here is a good workaround, with
typescript 4.5.5
sw.ts
@Tetr4 using an empty import caused an error for me:
Adding
export default null
instead ofimport { } from "."
in the service worker silenced the error.As a workaround I am currently doing this
Anyone have a better solution?
With TypeScript 4.3, I now have the following:
The
no-default-lib
is needed to workaround the fact thatself
is also aWindow
and not castable. Of course, now, you must usesw
and notself
😞@soryy708 You’re mistaken. Typescript supports either TS files or JSDocs syntax. In fact, it’s part of the official proposal.
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
https://github.com/tc39/proposal-type-annotations
Any progress about this? It’s kinda sad that we cannot use Service Workers alongside Type Script.
Using the lib Triple-Slash Directive
/// <reference lib="WebWorker" />
makesServiceWorkerGlobalScope
availableand no-default-lib Triple-Slash Directive
/// <reference no-default-lib="true"/>
disables the DOM library as Glandos points out:However, if I use these directives in my webworker’s source file, other files in my project (and inside node_modules) choke because they can no longer find the DOM stuff (Window, HTMLCollection, document, etc…)
The docs say:
Looks like using these directives is global, therefore pretty much equivalent to setting
lib
intsconfig.json
, which is unexpected. I expected the Triple-Slash directive to be local to the file in which it is written.Related: https://github.com/Microsoft/TypeScript/issues/20595
Possible solution: https://joshuatz.com/posts/2021/strongly-typed-service-workers/#solution-b-tsconfig-libs
@clshortfuse JSDoc isn’t related to TypeScript and isn’t Microsoft’s responsibility. Regarding your issue with JS only (JSDoc), try asking JSDoc instead. https://github.com/jsdoc/jsdoc
@abarisain I came up with your solution as well but it fails with following error
How did you configure your tsconfig.json to have it working? Thanks!
The workaround I found was:
…but you then have to use
_self
everywhere 😦I’m wondering whether we need to separate typings of web worker and service worker for the following reasons:
clients
.close
is not accessible in service worker, how can we omitclose
inServiceWorderGlobalScope
?clients
registration
viaself
in Chrome 57.(Just like theself
in Window)Does anybody have a JS only solution (jsdoc syntax)?
I got as far as:
But I’d have to change all references to
self
. I can’t manage to enforce it onself
.Would yield
Cannot redeclare block-scoped variable 'self'.ts(2451)
.If I try just importing the the lib, It can’t find it:
File '/home/user/project/node_modules/typescript/lib/lib.webworker.d.ts' is not a module.ts(2306)
self
is used in multiple works, so TypeScript may need to specify in the configuration which files refer to which worker types .after adding bun-types to qwik project, ServiceWorkerGlobalScope type lost it’s reference and result in TS compile error.
this hint helped me.
My current favorite workaround:
@clshortfuse
We need to cast to unknown first, to remove the error about incompatible types. It is not very pretty, but at least just two lines overall. This seems to work today without any errors and full Intellisense:
The workaround described in this issue doesn’t appear to work anymore in TypeScript 4.1 because it actually puts the
export
statement into the build output now, which fails evaluation in the browser.@Tetr4 I got errors using your approach as I then got duplicated references between
dom
andwebworker
.I ended up having to build a referenced tsconfig.json with two library configs (kind of like this), which seemed to work ok, but then with
export default null
at the top, that was copied into my JavaScript output asexports.__esModule
and caused errors during registration.So, I still have some configuration issue, but I’m pretty close.
I have not found references in the sepec that
self
is of typeServiceWorkerGlobalScope
.I think
clients
should be available as a global variable though. i.e.:In TypeScript 4.1+ it seems you can still get it working if you something like this
at the top of your file, and then use
sw
whenever you need to useself
. But it’s a very ugly workaround.Are you using the latest typescript version?
Turns out since I commented, my needs evolved: I needed to define new variables on the global scope. Since my project mixes a lot of environments, I also had to have many sub .tsconfig files.
Here is what works for me:
serviceworker-patches.d.ts
has some other patches to fix the incomplete definitionshere is my tsconfig
(the extend part is irrelevant, as all options defined in my base tsconfig are for other stuff)
I did this:
Note you need “webworker” lib with 2.4
self
property will return browsing context object. And according to MDN, sometimes returnServiceWorkerGlobalScope
object. See following docs.