Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at the New York ColdFusion User Group (Feb. 2009) with: Clark Valberg and Joakim Marner
Ben Nadel at the New York ColdFusion User Group (Feb. 2009) with: Clark Valberg@clarkvalberg ) and Joakim Marner

Using Firebase 4 With TypeScript, Type Declarations, And npm

By Ben Nadel on

In the past, I've used Firebase with Angular; but, it was with Angular 1.x, which pre-dated the use of TypeScript. Now that I'm loving TypeScript (especially with Angular), I want to be able to use Firebase 4 with type-safety. Unfortunately, using type declarations with Firebase 4 was kind of confusing to me (and my unfrozen caveman lawyer brain). So, I thought I would put together a quick demo in case anyone else stumbled over this same use-case.

To be clear, Angular has an official wrapper around Firebase called AngularFire. But, Angular isn't the only place that TypeScript and Firebase can come together. You can use Firebase in any TypeScript application. As such, I wanted to get this demo working outside of Angular, in a stand-alone TypeScript application compiled with Webpack.

From what I've read, Firebase can use the "Definitely Typed" library to serve type definitions through "@types/firebase". However, if you're using npm to load Firebase (such as with a Webpack-based build process), you can use the type definitions that ship directly with the Firebase module.

The Firebase module doesn't export interfaces - it exports a single object that can be imported using the import-require syntax in TypeScript. Using this single object, you can then access the type definitions using a series of namespaces. For example, the imported "firebase" module gives you access to interfaces like:

  • firebase.app.App
  • firebase.database.Database
  • firebase.database.Reference
  • firebase.database.DataSnapshot
  • firebase.auth.Auth
  • firebase.User
  • firebase.messaging.Messaging

To these type definitions in action, I've created a simple TypeScript file that attempts to write-to and read-from a Firebase application:

  • // Import the core node modules.
  • import firebase = require( "firebase/app" );
  •  
  • // Import the other firebase modules for their SIDE-EFFECTS! These imports will augment
  • // the App module and provide the type-definition for the .database() method.
  • import "firebase/database";
  •  
  • // ----------------------------------------------------------------------------------- //
  • // ----------------------------------------------------------------------------------- //
  •  
  • // Initialize the Firebase application.
  • // --
  • // NOTE: Obviously, I'm obfuscating my app credentials here.
  • var app: firebase.app.App = firebase.initializeApp({
  • apiKey: "****************",
  • authDomain: "****************",
  • databaseURL: "****************",
  • projectId: "i****************",
  • storageBucket: "****************",
  • messagingSenderId: "****************"
  • });
  •  
  • // Access the real-time database in the initialized application.
  • var db: firebase.database.Database = app.database();
  •  
  • // ----------------------------------------------------------------------------------- //
  • // ----------------------------------------------------------------------------------- //
  •  
  • // Try to write to and read back from Firebase.
  • (async function test() {
  •  
  • try {
  •  
  • var bennadel: firebase.database.Reference = db.ref( "testing/ben-nadel" );
  •  
  • await bennadel.set({
  • name: "Ben Nadel",
  • passions: [ "JavaScript", "TypeScript", "Angular", "ColdFusion", "UX" ]
  • });
  •  
  • var bennadelSnapshot: firebase.database.DataSnapshot = await bennadel.once( "value" );
  •  
  • console.log( "Firebase Ref Value:" );
  • console.dir( bennadelSnapshot.val() );
  •  
  • } catch ( error ) {
  •  
  • console.log( "Error!" );
  • console.log( error );
  •  
  • }
  •  
  • })();

As you can see, each of my variables is being declared with a type definition that is provided by the firebase module. The namespacing makes the declarations fairly verbose, which is why it might be wise to wrap your Firebase implementation in a Gateway / Repository class that can provide easier type inference. That said, when we compile this with Webpack and run it in the browser, we get the following page output:


 
 
 

 
 Using Firebase 4 with TypeScript, npm, and Webpack. 
 
 
 

As you can see, we were able to write to and read from the real-time Firebase database (also confirmed in the Firebase console, not shown). And, if we look at the Webpack / TypeScript build process, we can see that no errors were reported:


 
 
 

 
 Firebase 4 being compiled with TypeScript and type declarations. 
 
 
 

It took me over an hour to figure out how to get the type declarations working with Firebase in TypeScript. Maybe there was a simple ReadMe file that I was missing somewhere? No sure. But, if not, hopefully this will help anyone else who might be confused on where to find those interfaces and how to get them in your TypeScript logic.



Looking For A New Job?

Ooops, there are no jobs. Post one now for only $29 and own this real estate!

100% of job board revenue is donated to Kiva. Loans that change livesFind out more »

Reader Comments

@All,

So, it looks like I don't actually need to include the "database" script for its side-effects:

> import "firebase/database";

Matt Ferderer corrected me on this. I think the issue I was having is that it was erroring-out when I was trying to use the "Definitely Typed" libraries (which were not compatible with the latest version of Firebase). When I switched over to trying to use the Type definitions that ship with the Firebase module, I forgot (it didn't occur to me) to try compiling it without the added "import".

But, I can confirm (at least locally), that it all still compiles if I remove the import.

Reply to this Comment

@All,

An update on the snippet:

> import "firebase/database";

... it turns out, this IS needed; only, it's not needed for the type safety, it's needed for the side-effects. Meaning, without the import, the code will compile; but, if you try to run it in the browser, it will complain that .database() is not a runtime method.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.