2016-08-20 8 views
2

Я пытаюсь настроить GeoFire в своем приложении Angular2 (RC5). Я установил geofire и firebase с npm и сконфигурировал systemjs для его импорта. Вот мой package.json:Использование GeoFire в приложении Angular2

{ 
    "name": "MyProject", 
    "version": "0.1.0", 
    "scripts": { 
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ", 
    "lite": "lite-server", 
    "postinstall": "typings install", 
    "tsc": "tsc", 
    "tsc:w": "tsc -w", 
    "typings": "typings" 
    }, 
    "license": "ISC", 
    "dependencies": { 
    "@angular/common": "^2.0.0-rc.5", 
    "@angular/compiler": "^2.0.0-rc.5", 
    "@angular/core": "^2.0.0-rc.5", 
    "@angular/forms": "0.3.0", 
    "@angular/http": "2.0.0-rc.5", 
    "@angular/platform-browser": "^2.0.0-rc.5", 
    "@angular/platform-browser-dynamic": "^2.0.0-rc.5", 
    "@angular/router": "3.0.0-rc.1", 
    "@angular/router-deprecated": "2.0.0-rc.2", 
    "@angular/upgrade": "2.0.0-rc.5", 
    "angular2-in-memory-web-api": "0.0.15", 
    "bootstrap": "^3.3.6", 
    "core-js": "^2.4.0", 
    "firebase": "^3.3.0", 
    "geofire": "^4.1.1", 
    "reflect-metadata": "^0.1.3", 
    "rxjs": "5.0.0-beta.6", 
    "systemjs": "0.19.27", 
    "zone.js": "^0.6.12" 
    }, 
    "devDependencies": { 
    "concurrently": "^2.0.0", 
    "lite-server": "^2.2.0", 
    "typescript": "^1.8.10", 
    "typings": "^1.0.4" 
    } 
} 

и мой systemjs конфигурационный файл:

var map = { 
    'app':      'app', // 'dist', 
    '@angular':     'node_modules/@angular', 
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api', 
    'rxjs':      'node_modules/rxjs', 
    'firebase':     'node_modules/firebase', 
    'geofire':     'node_modules/geofire', 
    }; 
    // packages tells the System loader how to load when no filename and/or no extension 
    var packages = { 
    'app':      { main: 'main.js', defaultExtension: 'js' }, 
    'rxjs':      { defaultExtension: 'js' }, 
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, 
    'firebase':     { main: 'firebase.js', defaultExtension: 'js' }, 
    'geofire':     { main: 'dist/geofire.js', defaultExtension: 'js' }, 
    }; 

Наконец я пытаюсь импортировать geofire в моих app.component.ts файл следующим образом:

import * as GeoFire from "geofire"; 

Но при запуске npm начните транслировать и запускать сервер, получите следующую ошибку:

➜ MyProject npm start 

> [email protected] start /Users/max/Development/myproject 
> tsc && concurrently "npm run tsc:w" "npm run lite" 

app/app.component.ts(3,26): error TS2307: Cannot find module 'geofire'. 

npm ERR! Darwin 15.5.0 
npm ERR! argv "/usr/local/Cellar/node/5.10.1/bin/node" "/usr/local/bin/npm" "start" 
npm ERR! node v5.10.1 
npm ERR! npm v3.8.3 
npm ERR! code ELIFECYCLE 
npm ERR! [email protected] start: `tsc && concurrently "npm run tsc:w" "npm run lite" ` 
npm ERR! Exit status 2 
npm ERR! 
npm ERR! Failed at the [email protected] start script 'tsc && concurrently "npm run tsc:w" "npm run lite" '. 
npm ERR! Make sure you have the latest version of node.js and npm installed. 
npm ERR! If you do, this is most likely a problem with the MyProject package, 
npm ERR! not with npm itself. 
npm ERR! Tell the author that this fails on your system: 
npm ERR!  tsc && concurrently "npm run tsc:w" "npm run lite" 
npm ERR! You can get information on how to open an issue for this project with: 
npm ERR!  npm bugs MyProject 
npm ERR! Or if that isn't available, you can get their info via: 
npm ERR!  npm owner ls MyProject 
npm ERR! There is likely additional logging output above. 

npm ERR! Please include the following file with any support request: 
npm ERR!  /Users/max/Development/MyProject/npm-debug.log 

Вот мой TSconfig:

{ 
    "compilerOptions": { 
    "target": "es5", 
    "module": "commonjs", 
    "moduleResolution": "node", 
    "sourceMap": true, 
    "emitDecoratorMetadata": true, 
    "experimentalDecorators": true, 
    "removeComments": false, 
    "noImplicitAny": false 
    } 
} 

Остальные файлы проекта основаны на angular2 QuickStart здесь:

https://angular.io/guide/quickstart

ли кто-нибудь есть какие-либо идеи, как я могу получить TSC, чтобы найти модуль и успешно перевести?

Спасибо. Максимум.

+1

Вырезано: https://github.com/firebase/geofire-js/issues/116 –

+0

Вы используете tsc из командной строки? Это не будет работать с SystemJS, вам нужно будет использовать https://github.com/frankwallis/plugin-typescript/ и перераспределить его во время выполнения (systemjs сделает это за вас) или с помощью systemjs-builder. – artem

+0

@artem сообщение об ошибке отображается как при запуске tsc из командной строки, так и при запуске npm start. Я добавил полное сообщение об ошибке и полное содержимое package.json в исходный вопрос. –

ответ

6

В этом учебном руководстве по быстрому старту отсутствует один важный момент: SystemJS и TypeScript - это два отдельных инструмента, каждый со своей собственной конфигурацией.

Добавление geofire в конфигурацию systemjs не влияет на разрешение на тип машинописного текста. Увидев этот импорт

import * as GeoFire from "geofire"; 

TSC пытается найти geofire.ts в обычных местах, где типизации для яваскрипта модулей обычно находятся, и выдает ошибку, потому что это не было.

Существует три различных способа решения этой проблемы.

В любом случае, geofire конфигурации пакета в systemjs.config.js должен объявить свой формат, как global, как это:

'geofire': { 
    main: 'dist/geofire.js', 
    defaultExtension: 'js', 
    meta: {'dist/geofire.js': {format: 'global'}} 
}, 

Первое решение заключается в создании наиболее простой декларации типа для geofire себя, используя окружающие модули.

Создать geofire.d.ts файл в папке приложения:

declare namespace geofire { 
    function GeoFire(firebaseRef: any): void; 
} 

declare module 'geofire' { 
    export = geofire; 
} 

Этого достаточно для импорта заявление компилировать, и для этого вызова typecheck:

var geoFire = new GeoFire(firebaseRef); 

Примечание для машинописи 2.0

Для машинописных версий 2.0 приведенный выше код не работает.Вы должны использовать машинопись специфические import = синтаксис

import GeoFire = require('geofire'); 

и изменить определение в geofire.d.ts для:

declare module 'geofire' { 
    function GeoFire(firebaseRef: any): void; 
    export = GeoFire; 
} 

Еще один возможный способ решения этой проблемы является использование plugin для SystemJS, который использует машинопись API для вызова машинописный текст и привязка к его разрешению модуля, так что он учитывает конфигурацию SystemJS. С этим плагином этот импорт будет работать во время выполнения в браузере, но вызов tsc из командной строки все равно даст ту же ошибку.

Третий способ импортировать geofire с помощью SystemJS API, а не оператор импорта в app.component.ts:

import { Component } from '@angular/core'; 

declare var SystemJS : any; 
var GeoFirePromise = SystemJS.import('geofire'); 

@Component({ 
    selector: 'my-app', 
    template: '<h1>My First Angular 2 App</h1>' 
}) 

export class AppComponent { 

    constructor() { // or wherever you need to use geofire 

     GeoFirePromise.then(function(GeoFire: any) { 
      console.log(typeof GeoFire); 
     }); 
    } 

} 

Обратите внимание, что SystemJS.import возвращается обещание, что будет загружать geofire.js, поэтому в любом месте вы хотите использовать его, вы должны сделать

GeoFirePromise.then(function(GeoFire: any) { 

Если это неудобно, можно просто объявить глобальную переменную GeoFire

declare var GeoFire: any; 

и загрузите geofire.js с помощью скриптового тега в свой HTML, как описано в this post on ionic forum. Тогда вам не понадобится добавить geofire в systemjs.config.js.

+0

Спасибо за такой ясный и всесторонний ответ, @artem. Вы помогли прояснить некоторые недоразумения, которые у меня были о двух инструментах. Я отправился на маршрут geofire.d.ts, поскольку я думал, что это самый чистый. Макс –

+0

Привет снова @artem. Решение работало, пока я не создал сценарий firebase.d.ts, теперь tsc показывает эту ошибку: app/app.component.ts (37,19): ошибка TS2351: не может использовать «новое» с выражением, чей тип не имеет вызывать или создавать подпись - когда я пытаюсь это сделать: var geoFire = new GeoFire (firebaseRef) ;. Ошибка сохраняется даже после удаления файла firebase.d.ts. Любая идея почему? –

+1

Извините, я еще не знаю, как правильно это сделать на typecheck. Обходной путь, который я нашел до сих пор, заключается в том, чтобы обойти проверку типов через var X: any = GeoFire; var geofire = new X (...); – artem

3

Обратите внимание: я по-прежнему не являюсь экспертом по TypeScript, и это мой первый раз, когда я описываю определения типов и т. Д., Но после долгого рабочего дня у меня, похоже, есть что-то, что работает (по крайней мере, для моей настройки). Я использую Ionic 2 RC2, Angular2 2.1.1, Geofire 4.1.2. В сборке используется webpack. Я создал geofire.d.ts в моем каталоге приложения со следующим:

declare module 'geofire' { 

    type EventType = 'ready' | 'key_entered' | 'key_exited' | 'key_moved'; 

    interface GeoQueryCriteria { 
     center: number[]; 
     radius: number; 
    } 

    interface GeoQueryUpdateCriteria { 
     center?: number[]; 
     radius?: number; 
    } 

    interface GeoCallbackRegistration { 
     cancel(); 
    } 

    interface GeoQuery { 
     center(): number[]; 
     radius(): number; 
     updateCriteria(criteria: GeoQueryUpdateCriteria); 
     on(eventType: EventType, callback: (key:string, location: number[], distance: number) => void): GeoCallbackRegistration; 
     cancel(); 
    } 

    class GeoFire { 
     constructor(ref: any); 
     ref(): any; 
     set(key: string, loc: number[]): Promise<void>; 
     get(key: string): Promise<number[]>; 
     remove(key: string): Promise<void>; 
     query(criteria: GeoQueryCriteria): GeoQuery; 
     static distance(location1: number[], location2: number[]); 
    } 

    export = GeoFire; 
} 

Наконец в моей службы/Страница я могу импортировать GeoFire так:

import GeoFire from 'geofire';

Обратите внимание на точный синтаксис импорта там не фигурные скобки {}. Я пробовал так много способов заставить его работать по-другому, но я думаю, как писал javascript, так оно и должно быть сделано. Я нашел способы избавиться от ошибок компиляции, но сбой во время выполнения («no constructor named ...»), или он распознает конструктор в компиляции, но не как тип.

Я создал его только для общедоступного API, поэтому, если вы попытаетесь расширить GeoFire, по какой-то причине имейте в виду, что могут быть конфликты имен с другими методами, которые не отображаются в этом файле определения.

Если это поможет вам, пожалуйста, сообщите мне, и я пожертвую его DefinitelyTyped, так что больше никто не должен испытывать боль, которую я (и, очевидно, другие, имеющие более 340 просмотров).

+0

No {} on import исправил это для меня, спасибо! – Jon

+0

У меня есть ошибка: TypeError: geofire_1.default не является конструктором. Любое решение, как его исправить? –

+0

Где ошибка? Компилировать, работать? – DeezCashews