If you’re using Mongoose with TypeScript on your NodeJS project with RxJS you’ll probably want to avoid using promises as much as possible. Here’s an extension method on the Mongoose.

This will allow you to do something like this:

1
var rx_foundUser : Observable<User> = User.findOne({username: 'max'}).toObservable();

Currently if you want to use mongoose with TypeScript then you’ll have to resort to something like this

1
2
3
4
5
6
7
8
import {Observable} from '@reactivex/rxjs'
var promise = User.findOne({username: 'max'}).exec();
var rx_foundUser = Observable.fromPromise(promise);

rx_foundUser
.subscribe(user => {
console.log(`Your found user ${user.username}`)
})

This is quite verbose. So let’s create an extension method around it.

Make Sure You Have The Dependencies

Make sure you have your typings by running these commands

1
2
3
4
5
6
7
typings install dt~mongoose --global --save
typings install npm~mongodb --save
typings install npm~es6-promise --save

npm install mongoose --save
npm install @reactivex/rxjs --save
npm install es6-shim --save

Create an Extension Methods File

You’ll want to create an extensions file named something like extensions.ts. I put

Important: you’ll want to require this file immediately once at the beginning of your main execution file. For example, if you’re using this in ExpressJS and you have an app.js or server.js file, then you’ll want to require it like so:

1
2
3
4
5
//immediately upon execution, probably your first line
require('./custom/extension')

//do the rest of your app execution code here
var server = ...

The Extension Method File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export {} // This will turn this into a module. Don't forget it!

import {Observable, Subscriber} from '@reactivex/rxjs'
import {DocumentQuery, mquery} from 'mongoose'

declare module 'mongoose' {

interface mquery{
toObservable() : Observable<any>
}

interface DocumentQuery<T> {
toObservable() : Observable<T>
}
}

//This is where we do the actually implemention
mquery.prototype.toObservable = function() {
var query = this;
return Observable.fromPromise(query.exec())
}

Explainer

mongoose Is a popular library but it’s structure is quite nasty in terms of modern JavaScript patterns. This is a better exercise of creating extension methods in TypeScript.
If you take a look at the index.d.ts in the mongoose typings file, you’ll see that that queries are primarily subclassed from a type called mquery. The generic DocumentQuery<T> extends from mquery so we need to create an extension on both interfaces

The actual implemention that is mquery so we need to create the prototype method from that and not DocumentQuery<T>.

Mayhaps one day in TypeScript, creating extensions will be as easy as Swift or C#. Right now there’s a lot of training that you have to do with TypeScript and the underlying JavaScript context.