Modelling Cloudant data in TypeScript
Using TypeScript classes in your code and saving their JSON representation in a Cloudant database.
- type checking for function parameters, return values etc
- default and optional values for function parameters
- interfaces, for defining the shape of objects being passed in and out of functions
- classes with constructors, inheritance & access modifiers
- module import/export
- and lots more
In the above example, the red line indicates that there is no ‘postcode’ property of the
Address class. Catching mistakes like this in the editor saves lots of time later, chasing down errors and figuring out why the code isn't doing what is expected.
Data modelling with Cloudant
To take advantage of the features of TypeScript, it would be better if we could use classes instead of generic objects. We could build:
- a Date object to represent the time the employee joined.
- an Address object with custom methods that formats address lavels.
- a TagsCollection object with methods that allow new tags to be added and prevents duplicates.
Ideally, an Employee class containing these building-block classes would have a usuable JSON representation that could be stored in Cloudant. In addtion, the JSON string could be returned to a concrete class after retrieving data from the database.
There is a solution to this, so let’s start with a custom Address class.
We can create a custom TypeScript class that embodies a postal address and geo-location:
It’s worth explaining that a TypeScript Interfaces define the forms of objects — the attributes and types that make up an object. They are useful when defining functions that take objects as parameters — this allows the TypeScript compiler to check the form of the object at compile-time and allows your editor to check your code as you type.
This Address object is pretty simple. It has a number of public attributes that define the address, a
getLabel function that returns a postage label and a static
fromObject function that can resurrect an Address object from a generic object that conforms to the iAddress interface.
We’ll see how to incorporate this into our Employee class later, but first let’s look at how we can use a similar technique to model a date.
The CloudantDate class
In this blog post, I discussed various ways of representing a date/time in Cloudant JSON. I concluded that it’s good to have the constituent date/time parts (day, month, year) present in the object to allow Cloudant Query to access them and a “seconds since 1970” integer or an ISO-8601 string for sorting purposes.
fromObject function to allow a class to be reconstituted from an plain object. CloudantDate's real party piece is overridng the
toJSON function, which is used by
JSON.stringify to turn an instance of the class into JSON.
If we create a CloudantDate object and
JSON.stringify it, the resultant string contains all the date and time pieces broken out:
This allows us to have dates that are useable
Date classes in our code and have the constituent parts broken down in the Cloudant database, where they are accessible to the Cloudant indexing engine.
Our final storage class is TagCollection which stores an array of strings. It has a couple of helper functions (
remove) and also overrides the
toJSON function to ensure that only an array of strings appears in the JSON:
Assembling the Employee class
Now we have all the pieces in place, we can create a top level “Employee” class that uses our custom classes:
We have a base class that handles the Cloudant-specific fields (
_rev etc) which we can reuse across all of our Cloudant storage classes:
We can then use the Employee class in our own code and pass instances of Employee to the official Node.js Cloudant library to be stored in the database:
The Cloudant library converts the our custom object to JSON, which invokes our custom
The Cloudant document can be restored into an Employee class later, if we use our static
Employee.fromObject method to reconstitute the class from its JSON form:
toJSON function in your custom TypeScript classes allows you to use classes in your code and pass them to the Cloudant Node.js library to be saved in a form of JSON of your choice.