ServiceWorker 的 TypeScript 类型定义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38172450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TypeScript type definitions for ServiceWorker
提问by James B
I'm writing a service for my angular 2 app using TypeScript. The service makes use of chrome's ServiceWorker
to listen for push notifications (see tutorial). The code (javascript) makes use of navigator
first to see if serviceWorker
is supported, then continues to complete registration etc., i.e.,
我正在使用 TypeScript 为我的 angular 2 应用程序编写服务。该服务使用 chromeServiceWorker
来侦听推送通知(请参阅教程)。代码(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);
});
}
I'd like to implemenet the above using TypeScript. However, the current lib.d.ts
used by the TypeScript compiler (see below) appears to have no definitions defined on Navigator
for the serviceWorker
or its associated methods such as serviceWorker.register
(I guess since it's a chrome-specific implementation).
我想使用 TypeScript 实现上述内容。但是,lib.d.ts
TypeScript 编译器使用的当前版本(见下文)似乎没有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;
}
The result is that I'm faced with compilation errors since the compiler can't find the associated serviceWorker
types. Given I'm new to JavaScript and TypeScript, I'm trying to determine the best way to proceed. I understand the options to be:
结果是我面临编译错误,因为编译器找不到关联的serviceWorker
类型。鉴于我是 JavaScript 和 TypeScript 的新手,我正在尝试确定继续进行的最佳方式。我理解的选项是:
- Keep the js code and simply ignore the compilation errors (not ideal).
- Keep the js code and somehow suppress the type errors during compilation.
- Find an existing typescript definitions library that
has
serviceWorker
defined and include that during compilation. - Write my own typescript definition file for navigator or somehow
extend the existing
lib.d.ts
- 保留 js 代码并简单地忽略编译错误(不理想)。
- 保留 js 代码并在编译期间以某种方式抑制类型错误。
- 查找已
serviceWorker
在编译期间定义并包含的现有打字稿定义库。 - 为导航器编写我自己的打字稿定义文件或以某种方式扩展现有的
lib.d.ts
Sage advice on the best option greatly appreciated.
非常感谢圣人关于最佳选择的建议。
Update
更新
Attempted to cast to any to remove compilation errors, i.e.,
尝试强制转换为 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);
});
but now facing new errors, i.e.,
但现在面临新的错误,即
error TS7006: Parameter 'reg' implicitly has an 'any' type.
error TS7006: Parameter 'error' implicitly has an 'any' type.
Also, tempted to write definitions for the ServiceWorker using these details. However never done it before, so will need some practice!
此外,还想使用这些细节为 ServiceWorker 编写定义。但是以前从来没有做过,所以需要一些练习!
回答by Maxim Egorushkin
Type definitions for ServiceWorker and friendsare now available from DefinitelyTyped/service_worker_api:
ServiceWorker 和朋友的类型定义现在可以从DefinitelyTyped/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 as necessary.
根据需要调整路径。
回答by tiernanx
Original Answer
原答案
Here are the Typings I created to use with WebStorm: Gist.
以下是我创建的用于 WebStorm 的 Typings:Gist。
Then in my service-worker.ts file I include a reference: /// <reference path="YOUR_PATH_HERE/service-worker.d.ts" />
.
然后在我的 service-worker.ts 文件中包含一个引用:/// <reference path="YOUR_PATH_HERE/service-worker.d.ts" />
.
Adjust your path accordingly, or make them global and you should be pretty set. It's fairly complete, but I'm sure it's missing some things. Anyway, I hope this helps.
相应地调整您的路径,或将它们设为全局,您应该已经设置好了。它相当完整,但我确定它缺少一些东西。无论如何,我希望这会有所帮助。
2018 Update:
2018 更新:
I published a new edition of these definitions to work with lib.webworker.d.ts along with any es5+ library (lib.es5.d.ts, lib.es2015.d.ts, etc) here: Service Worker Typings to Supplement lib.webworker.d.ts. This set should be much more relevant today.
我在此处发布了这些定义的新版本以与 lib.webworker.d.ts 以及任何 es5+ 库(lib.es5.d.ts、lib.es2015.d.ts 等)一起使用:Service Worker Typings to Supplement lib .webworker.d.ts。这个集合在今天应该更相关。
回答by AngJobs on Github
You can add to the interface in your TypeScript file and when the lib.d.ts is updated, the compiler will tell you that you no longer need it.
您可以在 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) { }
);
or
或者
Instead of changing the definition you can cast to an any
object an call with arbitray parameters e.g:
您可以将any
具有任意参数的调用转换为对象,而不是更改定义,例如:
var n = <any>navigator;
n.getUserMedia = n.getUserMedia || n.webkitGetUserMedia || n.mozGetUserMedia || n.msGetUserMedia;
return n.getUserMedia({video: true, audio:true}, onSuccess, onFail);
回答by Sourav Paul
ServiceWorker is not a chrome specific extension.
ServiceWorker 不是 chrome 特定的扩展。
OP should refer to Jake Archibald's isSERVICEWORKERready?page for a rundown of the current state of ServiceWorker in the popular browsers.
OP 应该是指 Jake Archibald 的isSERVICEWORKERready?页面,了解流行浏览器中 ServiceWorker 的当前状态。
I added the type definitions in tsd.d.ts
based on the interface information linkedby OP and they seem to be working.
我tsd.d.ts
根据OP链接的接口信息添加了类型定义,它们似乎正在工作。
Please notethat I referenced IPromise
interface from angular.d.ts.
请注意,我IPromise
从angular.d.ts引用了接口。
Defined in tsd.d.ts
定义于 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;
}
Referred in home-controller.ts
参考文献 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.');
}
}
Building and loading the app in the chrome
在 chrome 中构建和加载应用程序
logs the following console message:
记录以下控制台消息:
Hope this helps.
希望这可以帮助。