I\'m trying to set up GeoFire in my Angular2 (RC5) app. I\'ve installed geofire and firebase with npm and configured systemjs to import it. Here\'s my package.json:
That quickstart tutorial is missing one important point: SystemJS and TypeScript are two separate tools, each with its own configuration.
Adding geofire to systemjs config has no effect on typescript module resolution. Upon seeing this import
import * as GeoFire from "geofire";
tsc tries to find geofire.ts in usual places where typings for javascript modules are normally found, and gives an error because it's not there.
There are three different ways to solve this problem.
In any case, geofire package configuration in systemjs.config.js must declare its format as global, like this:
'geofire': {
main: 'dist/geofire.js',
defaultExtension: 'js',
meta: {'dist/geofire.js': {format: 'global'}}
},
The first solution is to create the simplest possible type declaration for geofire yourself, using ambient modules.
Create geofire.d.ts file in the app folder:
declare namespace geofire {
function GeoFire(firebaseRef: any): void;
}
declare module 'geofire' {
export = geofire;
}
This is sufficient for import statement to compile, and for this call to typecheck:
var geoFire = new GeoFire(firebaseRef);
NOTE for typescript 2.0
For typescript 2.0 the code above does not work. You have to use typescript-specific import = syntax
import GeoFire = require('geofire');
and change definition in geofire.d.ts to:
declare module 'geofire' {
function GeoFire(firebaseRef: any): void;
export = GeoFire;
}
Yet another possible way to solve this is to use a plugin for SystemJS that uses TypeScript API to invoke typescript and hook into its module resolution, so that it takes into account SystemJS configuration. With that plugin, that import will work at runtime in the browser, but invoking tsc from the command line would still give the same error.
The third way is to import geofire using SystemJS API, not the import statement in app.component.ts:
import { Component } from '@angular/core';
declare var SystemJS : any;
var GeoFirePromise = SystemJS.import('geofire');
@Component({
selector: 'my-app',
template: 'My First Angular 2 App
'
})
export class AppComponent {
constructor() { // or wherever you need to use geofire
GeoFirePromise.then(function(GeoFire: any) {
console.log(typeof GeoFire);
});
}
}
Note that SystemJS.import returns a promise that will have to load geofire.js, so anywhere you want to use it you have to do
GeoFirePromise.then(function(GeoFire: any) {
If this is inconvenient, you can just declare global GeoFire variable
declare var GeoFire: any;
and load geofire.js using script tag in your HTML, as described in this post on ionic forum. Then, you would not event need to add geofire to systemjs.config.js.