2016-07-03 5 views
5

Я пишу службу для своего приложения с угловым 2, используя TypeScript. Сервис использует хром ServiceWorker для прослушивания push-уведомлений (см. tutorial). Код (JavaScript) использует navigator первых, чтобы увидеть, если serviceWorker поддерживается, то продолжает завершать регистрацию и т.д., т.е.Определения типа TypeScript для 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); 
    }); 
} 

Я хотел бы implemenet выше с помощью машинописи. Однако текущий lib.d.ts, используемый компилятором TypeScript (см. Ниже), по-видимому, не имеет определений, определенных в Navigator, для serviceWorker или связанных с ним методов, таких как serviceWorker.register (я предполагаю, что это реализация, специфичная для хрома).

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 и просто игнорировать ошибки компиляции (не идеал).
  2. Сохраните код js и как-то подавите ошибки типа во время компиляции.
  3. Найдите существующую библиотеку определений типов писем, которую имеет serviceWorker, и укажите, что во время компиляции.
  4. Написать свой собственный файл определение машинописи для навигатора или какой-то образом продлить существующий lib.d.ts

Sage советы по самому лучшему варианту весьма признателен.

Update

Пытался бросить любому удалить ошибки компиляции, т.е.

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, используя эти details. Однако никогда не делал этого раньше, так что потребуется какая-то практика!

ответ

1

Вы можете добавить к интерфейсу в свой файл 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 объекта вызова с arbitray параметрами: например

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

Кастинг был бы самым простым решением, однако попытка наложить на '' дает ошибку 'TS7006: параметр 'reg' неявно имеет тип 'any'. - см. обновление. –

1

ServiceWorker не является специальное расширение хром.

OP должен ссылаться на страницу isSERVICEWORKERready? Джейка Арчибальда для краткого изложения текущего состояния ServiceWorker в популярных браузерах.

Я добавил определения типов в tsd.d.ts на основе информации интерфейса linked от OP, и они, похоже, работают.

Обращаем внимание, что я ссылаюсь на IPromise интерфейс от angular.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; 
} 

Приглашен в 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.'); 
    } 
} 

Строительство и загрузки приложения в хроме

enter image description here

регистрирует следующую консольную сообщение:

enter image description here

Надеется, что это помогает.

2

Ниже приведены Типики, которые я создал для использования с WebStorm: Gist.

Тогда в моем файле service-worker.ts я включаю ссылку: /// <reference path="YOUR_PATH_HERE/service-worker.d.ts" />.

Настройте свой путь соответствующим образом или сделайте их глобальными, и вы должны быть достаточно настроены. Это довольно полно, но я уверен, что это не так. Во всяком случае, я надеюсь, что это поможет.

+1

Это замечательно! Сделано несколько (поэтапных) обновлений: https://gist.github.com/ithinkihaveacat/227bfe8aa81328c5d64ec48f4e4df8e5 – mjs

+0

@mjs Спасибо за ваш вклад! Я внес свои изменения с небольшими изменениями. – tiernanx

5

определения типа для ServiceWorker and friends теперь доступны DefinitelyTyped/service_worker_api: пример

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

Использование:

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

Настройка путей по мере необходимости.

+1

Начиная с TypeScript 2.0, 'npm install --save @ types/service_worker_api' [также будет работать] (https://blogs.msdn.microsoft.com/typescript/2016/06/15/the-future-of-declaration -файлы /). – mjs

+0

@mjs Это очень приятное улучшение. –

Смежные вопросы