-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Service Worker typings #11781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Since service workers run in their own context, i suppose we need @zhengbli can we update our declaration files to pull in serviceworker spec idl as well |
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
So instead I have to use interface Window extends ServiceWorkerGlobalScope {} to attach interfaces onto This brings some other problems, eg. I must change the incompatible properties like // expected
interface ServiceWorkerGlobalScope {
onmessage: (messageevent: ExtendableMessageEvent) => void;
}
// now
interface ServiceWorkerGlobalScope {
onmessage: (messageevent: MessageEvent) => void;
} 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 |
Anyone know how I can force TS to change the type of |
first you need |
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? |
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. |
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. |
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 |
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. |
I'm addressing the issue like this. Currently works well. https://gist.github.com/shqld/32df51a4a4ed429f2c76e4e2cfdf6f96#gistcomment-2793376 |
And created a package https://github.com/shqld/types-serviceworker (If this violates licenses, please tell me) |
@caseyhoward The PR removing Service Worker API is DefinitelyTyped/DefinitelyTyped#14786 Agreed, the "dom lib" message is incorrect. I got it seemingly working with @shqld Thanks for this! Edit: I've tried both methods. Many hacks are required to use the |
For anyone else who comes upon this thread, there seems to be 2 main solutions:
A few additional notes: I had a setup where the broader project had many typings installed via To ensure that this works, make sure you include |
It would make things much easier if we could declare a script's environment with triple-slash directives. These could override any configuration that is being used.
ESLint provides a similar solution.
Most of the development teams that I know tend to push TS scripts through Babel and Webpack, and need a simple way to target multiple environments in one TS code base so VSCode (and friends) can provide the correct APIs (code hints etc). |
The way the service worker issue was resolved here was by adding const initialize = (service: ServiceWorkerGlobalScope): void => {
service.addEventListener("install", ... )
}
initialize(self as any) Not ideal, because the service worker APIs are now picked up by all of the scripts in the project, but at least this way we have access to the service worker type definitions. |
@simon-robertson you can, see https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-lib- /// <reference lib="webworker" /> |
I did the following and it worked for my needs e.g.: /// <reference no-default-lib="true"/>
/// <reference lib="es2015" />
/// <reference lib="webworker" />
interface Window extends ServiceWorkerGlobalScope {}
self.addEventListener("fetch", (event: FetchEvent) => {
event.respondWith(caches.match(event.request));
}); |
Short of breaking up a project into multiple workspace projects, I guess that would be the best solution for now. I was thinking of something more along the lines of ...
Essentially overriding the libraries specified in the tsconfig.json file for isolated use cases. |
Which lib I need for …videlicet… I added InstallEvent code looks like: sw.addEventListener( 'install', function ( /** @type {InstallEvent} */ event )
{
//…
}); where Someone understand it? Do I missing some lib for InstallEvent? |
For JavaScript, the following snippet helped to bring IntelliSense to Visual Studio Code by making use of JSDoc: // service-worker.js
/// <reference no-default-lib="true"/>
/// <reference lib="es2015" />
/// <reference lib="webworker" />
/**
* @type {ServiceWorkerGlobalScope}
*/
const sw = self;
sw.addEventListener("install", event => {
console.log(event);
console.log(sw.caches);
console.log(sw.registration);
}); |
Not aliasing self works if you are writing a web worker, but to use the service worker events like install, you can't just use What I ended up using today is: const sw: ServiceWorkerGlobalScope & typeof globalThis = self as any alongside separate tsconfigs that specify different libs and includes (and extend a common base). |
I don't know if this is a good idea, but one could, instead of aliasing self, change the typing of self with something like: declare var self: ServiceWorkerGlobalScope & typeof globalThis; |
At least my TypeScript 4.0 setup is not happy:
|
With TypeScript 4.3, I now have the following: /// <reference no-default-lib="true"/>
/// <reference lib="es2020" />
/// <reference lib="WebWorker" />
const sw = self as ServiceWorkerGlobalScope & typeof globalThis The |
for jsdoc and vanilla js developers: /// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="WebWorker" />
const sw = /** @type {ServiceWorkerGlobalScope & typeof globalThis} */ (globalThis) |
jimmywarting thanks for that solutions, even tho, it gave me another error, now from ESLint:
as well as TypeScript gave error:
So I did this: /// env serviceworker
const globalThis = /** @type {unknown} */ (self);
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="WebWorker" />
const sw = /** @type {ServiceWorkerGlobalScope & typeof globalThis} */ (globalThis) yeah, that's crazy. |
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 than it should be. This rewrite was all from last night, and it took a few hours to learn how to get things right (I didn't get around to commiting it until now though). There aren't any type errors anymore, but I'm also unsure if it will run sucessfully yet. I don't have a device/OS to test the Web Share Target API support anymore, since my Chromebook runs Ubuntu now :) While it's not fully functional yet, this is a step in the right direction for type-safe Service Worker code! I mostly rewrote it with my new programming styles, expanding things out for readability, and making use of async-await where it was previously just `.then()` calls and such. Some help to get it working: https://github.com/NicholasPeretti/service-worker-ts-example https://stackoverflow.com/questions/89332/how-do-i-recover-a-dropped-stash-in-git (I had an oopsie XD) Edit: Tried testing out the worker in the browser, and modern TypeScript now includes empty `export {}` instances in the resulting JS, which breaks declaring the file as a module, as you can't have `export {}` in a non-module script. The only way I got close to this was to name the file `.mts`, but I'm not sure if I like that or not. But hey, it may work. With that being a possible solution, I found all of these sources along the way also: https://stackoverflow.com/questions/56356655/structuring-a-typescript-project-with-workers https://github.com/jakearchibald/typescript-worker-example (now outdated, unfortunately, thanks to this new TypeScript change) microsoft/TypeScript#41513 https://www.devextent.com/create-service-worker-typescript/ (almost works! falls down to the same issue sadly) microsoft/TypeScript#14877 microsoft/TypeScript#11781
The simplest solution that worked for me, is just this on the Service Worker code: /// <reference lib="WebWorker" />
const sw: ServiceWorkerGlobalScope = self as any |
To avoid aliasing /// <reference lib="WebWorker" />
declare let self: ServiceWorkerGlobalScope; |
It gives an error: Cannot redeclare block-scoped variable 'self' Using this instead worked: /// <reference lib="WebWorker" />
export type {};
declare let self: ServiceWorkerGlobalScope; Yep, it's getting weirder 😆 |
This works for me (for now... 🤷🏻 ): /// <reference lib="esnext" />
/// <reference lib="webworker" />
/// <reference no-default-lib="true"/>
// service-worker.ts
(() => {
const initializeSW = (sw: ServiceWorkerGlobalScope) => {
sw.addEventListener('install', (event: ExtendableEvent) => {
// eslint-disable-next-line no-console
console.log(event);
});
// see: https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim
sw.addEventListener('activate', (event: ExtendableEvent) => {
// eslint-disable-next-line no-console
console.log(event);
event.waitUntil(sw.clients.claim());
});
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initializeSW(self as any);
})(); 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"]
}
"typescript": "^5.0.2", |
@icazemier ty :) adding to tsconfig.json:
|
Somehow /// <reference lib="esnext" />
/// <reference lib="webworker" />
/// <reference no-default-lib="true"/> preamble, together with 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 |
If you are using @vitejs, this works for me
build: {
rollupOptions: {
input: {
app: './index.html',
'sw': './src/sw.ts',
},
output: {
entryFileNames: assetInfo => {
return assetInfo.name === 'sw' ? '[name].js' : 'assets/[name]-[hash].js'
}
},
},
},
"compilerOptions": {
"lib": [
"WebWorker"
],
declare const self: ServiceWorkerGlobalScope;
self.addEventListener('install', (e: ExtendableEvent) => {
...
}); |
I got it working with this at the top of my worker code /// <reference lib="WebWorker" />
export type {}
declare let self: DedicatedWorkerGlobalScope |
It seems typings are missing for and thus there are no types for https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes |
TypeScript Version: 2.0.3
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.
The text was updated successfully, but these errors were encountered: