Using Firebase 4 With TypeScript, Type Declarations, And npm

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:

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:

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.

Tweet This Interesting post by @BenNadel - Using Firebase 4 With TypeScript, Type Declarations, And npm Woot woot — you rock the party that rocks the body!







