ServiceWorker的TypeScript类型定义

zzwlnbp8  于 2022-12-14  发布在  TypeScript
关注(0)|答案(4)|浏览(295)

我正在使用TypeScript为angular 2应用编写一个服务。该服务使用chrome的ServiceWorker来监听推送通知(参见tutorial)。代码(javascript)首先使用navigator来查看是否支持serviceWorker,然后继续完成注册等,即:

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);
  });
}

我想用TypeScript实现上面的方法。但是,TypeScript编译器(见下文)使用的当前lib.d.ts似乎没有在Navigator上定义serviceWorker或其相关方法,如serviceWorker.register(我猜是因为它是一个特定于chrome的实现)。

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;
}

结果是,我面临着编译错误,因为编译器找不到相关的serviceWorker类型。鉴于我是JavaScript和TypeScript的新手,我试图确定最好的方法来继续。我理解的选项是:
1.保留js代码并简单地忽略编译错误(不理想)。
1.保留js代码并在编译期间以某种方式抑制类型错误。
1.找到已定义serviceWorker的现有类型脚本定义库,并在编译期间将其包括在内。
1.为navigator编写自己的typescript定义文件或以某种方式扩展现有的lib.d.ts
非常感谢关于最佳选择的明智建议。

更新

试图强制转换为any以移除编译错误,即,

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);
    });

但现在面临新的错误,

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

同时,尝试使用这些细节为ServiceWorker编写定义。但是以前从未这样做过,所以需要一些练习!

2hh7jdfx

2hh7jdfx1#

ServiceWorker和friends的类型定义现在可从DefinitelyTyped/service_worker_api获得:

$ npm install --save @types/service_worker_api

用法示例:

// 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/' });
    }
}

根据需要调整路径。

vdzxcuhz

vdzxcuhz2#

您可以将添加到TypeScript文件中的接口,当lib.d.ts更新时,编译器会告诉您不再需要它。

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) {  }
);


您可以将带有任意参数的调用强制转换为any对象,而不必更改定义,例如:

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

chy5wohz3#

ServiceWorker不是特定于Chrome的扩展。
OP应该参考Jake Archibald的isSERVICEWORKERready?页面,了解流行浏览器中ServiceWorker的当前状态。
我根据OP链接的接口信息在tsd.d.ts中添加了类型定义,它们似乎正在工作。

请注意我从angular.d.ts引用了IPromise接口。

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;
}

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.');
  }
}

在chrome中构建和加载应用程序

记录以下控制台消息:

希望这对你有帮助。

lmyy7pcs

lmyy7pcs4#

原始答案

以下是我创建的用于WebStorm的类型:Gist
然后在我的service-worker.ts文件中包含一个引用:/// <reference path="YOUR_PATH_HERE/service-worker.d.ts" /> .
相应地调整你的路径,或者把它们变成全局的,你应该已经很确定了。它相当完整,但是我确信它遗漏了一些东西。无论如何,我希望这能有所帮助。

2018年更新:

我发布了这些定义的新版本,以便与lib.webworker.d.ts沿着任何es 5+库(lib.es5.d.ts、lib.es2015.d.ts等)一起使用:Service Worker Typings to Supplement lib.webworker.d.ts.这一套今天应该更相关。

相关问题