TypeScript type definitions for ServiceWorker

I am writing a service for my angular 2 application using TypeScript. The service uses chrome ServiceWorker to listen for push notifications (see the tutorial ). In the code (javascript), navigator is first used to see if ServiceWorker supported, then continues to register, etc., i.e.

 if ('serviceWorker' in navigator) { console.log('Service Worker is supported'); navigator.serviceWorker.register('sw.js').then(function() { return navigator.serviceWorker.ready; }).then(function(reg) { console.log('Service Worker is ready :^)', reg); // TODO }).catch(function(error) { console.log('Service Worker error :^(', error); }); } 

I would like to do the above using TypeScript. However, the current lib.d.ts used by the TypeScript compiler (see below) does not seem to have definitions defined in the navigator for ServiceWorker or related methods such as serviceWorker.register (I assume this is chrome-specific implementation).

 interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorUserMedia { readonly appCodeName: string; readonly cookieEnabled: boolean; readonly language: string; readonly maxTouchPoints: number; readonly mimeTypes: MimeTypeArray; readonly msManipulationViewsEnabled: boolean; readonly msMaxTouchPoints: number; readonly msPointerEnabled: boolean; readonly plugins: PluginArray; readonly pointerEnabled: boolean; readonly webdriver: boolean; getGamepads(): Gamepad[]; javaEnabled(): boolean; msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void; requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): PromiseLike<MediaKeySystemAccess>; vibrate(pattern: number | number[]): boolean; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } 

As a result, I ran into compilation errors because the compiler could not find the associated ServiceWorker types. Given that I'm new to JavaScript and TypeScript, I'm trying to determine the best way to continue. I understand the options:

  • Save the js code and just ignore compilation errors (not ideal).
  • Save the js code and somehow suppress type errors during compilation.
  • Locate an existing TypeScript definition library that has ServiceWorker defined and including that at compile time.
  • Write my own TypeScript definition file for the navigator or extend the existing lib.d.ts

Sage's best advice is greatly appreciated.

Update

An attempt to apply to anyone to remove compilation errors, i.e.

 var nav = <any> navigator; if ('serviceWorker' in nav) { nav.serviceWorker.register('sw.js') .then(function(reg) { console.log('yey!', <any> reg); }).catch(function(err) { console.log('boo!', <any> err); }); 

but now before new errors, i.e.

 error TS7006: Parameter 'reg' implicitly has an 'any' type. error TS7006: Parameter 'error' implicitly has an 'any' type. 

It is also tempting to write definitions for ServiceWorker using these details . However, I have never done this before, so it will take some practice!

+5
source share
4 answers

Type definitions for ServiceWorker and friends are now available from Definitely / Service _worker_api :

 $ typings install dt~service_worker_api --global --save service_worker_api └── (No dependencies) 

Usage example:

 // data-access.service.ts /// <reference path="typings/globals/service_worker_api/index.d.ts" /> import { Injectable } from '@angular/core'; @Injectable() export class DataAccess { constructor() { navigator.serviceWorker.register('service-worker.js', { scope: '/api/' }); } } 

Adjust the paths if necessary.

+5
source

Here are the ones I created for use with WebStorm: Gist .

Then, in the service-worker.ts file, I include the link: /// <reference path="YOUR_PATH_HERE/service-worker.d.ts" /> .

Adjust your path accordingly, or make them global, and you should be tuned enough. This is pretty complete, but I'm sure he missed some things. Anyway, I hope this helps.

+2
source

You can add a file to your TypeScript interface, and when lib.d.ts is updated, the compiler will tell you that it is no longer needed.

 interface Navigator { getUserMedia( options: { video?: bool; audio?: bool; }, success: (stream: any) => void, error?: (error: string) => void ) : void; } navigator.getUserMedia( {video: true, audio: true}, function (stream) { }, function (error) { } ); 

or

Instead of changing the definition, you can pass a call to the any object with arbitration parameters, for example:

  var n = <any>navigator; n.getUserMedia = n.getUserMedia || n.webkitGetUserMedia || n.mozGetUserMedia || n.msGetUserMedia; return n.getUserMedia({video: true, audio:true}, onSuccess, onFail); 
+1
source

ServiceWorker is not a chrome-specific extension.

OP should link to Jake Archibald isSERVICEWORKERready? to state the current status of ServiceWorker in popular browsers.

I added type definitions to tsd.d.ts based on the interface information associated with the OP, and they seem to work.

Pay attention to which I referenced the IPromise interface.

Defined in tsd.d.ts

 /// <reference path="angularjs/angular.d.ts" /> interface Navigator { serviceWorker: ServiceWorkerContainer; } interface ServiceWorkerContainer { register(scriptUrl: string, options?: RegistrationOptions): angular.IPromise<ServiceWorkerRegistration>; } interface RegistrationOptions { scope: string; } interface ServiceWorkerRegistration { installing?: ServiceWorker; waiting?: ServiceWorker; active?: ServiceWorker; scope: string; update(): angular.IPromise<void>; unregister(): angular.IPromise<boolean>; } interface ServiceWorker { scriptUrl: string; state: string; postMessage(message: any, transfer: Array<any>): void; } 

Applies to home-controller.ts

 ///<reference path='../../typings/tsd.d.ts' /> ... // dependencies are injected via AngularJS $injector constructor() { var vm = this; vm.ctrlName = 'HomeCtrl'; if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js', { scope: '/' }).then(function(reg) { // registration worked console.log('Registration succeeded. Scope is ' + reg.scope); }).catch(function(error) { // registration failed console.log('Registration failed with ' + error); }); } else { console.warn('serviceWorker not available in navigator.'); } } 

Creating and loading an application in chrome

enter image description here

writes the following console message:

enter image description here

Hope this helps.

+1
source

All Articles