In this tutorial you learn how to use RxDB with TypeScript. We will create a basic database with one collection and several ORM-methods, fully typed!
RxDB directly comes with it's typings and you do not have to install anything else, however the latest version of RxDB (v9+) requires that you are using Typescript v3.8 or higher. Our way to go is
- First define how the documents look like
- Then define how the collections look like
- Then define how the database looks like
First you import the types from RxDB.
import {
createRxDatabase,
RxDatabase,
RxCollection,
RxJsonSchema,
RxDocument,
} from 'rxdb';
First we have to define the TypeScript type of the documents of a collection:
import {
toTypedRxJsonSchema,
ExtractDocumentTypeFromTypedRxJsonSchema,
RxJsonSchema
} from 'rxdb';
export const heroSchemaLiteral = {
title: 'hero schema',
description: 'describes a human being',
version: 0,
keyCompression: true,
primaryKey: 'passportId',
type: 'object',
properties: {
passportId: {
type: 'string'
},
firstName: {
type: 'string'
},
lastName: {
type: 'string'
}
},
required: ['firstName', 'lastName', 'passportId'],
indexes: ['firstName']
} as const; // <- It is important to set 'as const' to preserve the literal type
const schemaTyped = toTypedRxJsonSchema(heroSchemaLiteral);
// aggregate the document type from the schema
type HeroDocType = ExtractDocumentTypeFromTypedRxJsonSchema<typeof schemaTyped>;
// create the typed RxJsonSchema from the literal typed object.
const heroSchema: RxJsonSchema<HeroDocType> = heroSchemaLiteral;
type HeroDocType = {
passportId: string;
firstName: string;
lastName: string;
age?: number; // optional
};
If your schema is in a .json
file or generated from somewhere else, you might generate the typings with the json-schema-to-typescript module.
We also add some ORM-methods for the document.
type HeroDocMethods = {
scream: (v: string) => string;
};
We can merge these into our HeroDocument.
type HeroDocument = RxDocument<HeroDocType, HeroDocMethods>;
Now we can define type for the collection which contains the documents.
// we declare one static ORM-method for the collection
type HeroCollectionMethods = {
countAllDocuments: () => Promise<number>;
}
// and then merge all our types
type HeroCollection = RxCollection<HeroDocType, HeroDocMethods, HeroCollectionMethods>;
Before we can define the database, we make a helper-type which contains all collections of it.
type MyDatabaseCollections = {
heroes: HeroCollection
}
Now the database.
type MyDatabase = RxDatabase<MyDatabaseCollections>;
Now that we have declare all our types, we can use them.
/**
* create database and collections
*/
const myDatabase: MyDatabase = await createRxDatabase<MyDatabaseCollections>({
name: 'mydb',
storage: getRxStoragePouch('memory')
});
const heroSchema: RxJsonSchema<HeroDocType> = {
title: 'human schema',
description: 'describes a human being',
version: 0,
keyCompression: true,
primaryKey: 'passportId',
type: 'object',
properties: {
passportId: {
type: 'string'
},
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
age: {
type: 'integer'
}
},
required: ['passportId', 'firstName', 'lastName']
};
const heroDocMethods: HeroDocMethods = {
scream: function(this: HeroDocument, what: string) {
return this.firstName + ' screams: ' + what.toUpperCase();
}
};
const heroCollectionMethods: HeroCollectionMethods = {
countAllDocuments: async function(this: HeroCollection) {
const allDocs = await this.find().exec();
return allDocs.length;
}
};
await myDatabase.addCollections({
heroes: {
schema: heroSchema,
methods: heroDocMethods,
statics: heroCollectionMethods
}
});
// add a postInsert-hook
myDatabase.heroes.postInsert(
function myPostInsertHook(
this: HeroCollection, // own collection is bound to the scope
docData: HeroDocType, // documents data
doc: HeroDocument // RxDocument
) {
console.log('insert to ' + this.name + '-collection: ' + doc.firstName);
},
false // not async
);
/**
* use the database
*/
// insert a document
const hero: HeroDocument = await myDatabase.heroes.insert({
passportId: 'myId',
firstName: 'piotr',
lastName: 'potter',
age: 5
});
// access a property
console.log(hero.firstName);
// use a orm method
hero.scream('AAH!');
// use a static orm method from the collection
const amount: number = await myDatabase.heroes.countAllDocuments();
console.log(amount);
/**
* clean up
*/
myDatabase.destroy();
If you are new to RxDB, you should continue here