Recently I’ve been working a project titled Gitello, which attempts to be a sort of Trello clone with much better Git integration (I haven’t written about it much anywhere, I might do that soon.) It’s coded in NodeJS using ExpressJS and Sequelize (SQL) for the backend.
Now, Gitello has a huge codebase in JavaScript. There’s lots of files, objects, and especially lines. It has both a backend, and a frontend (both which are huge.) One big issue with all this code was type validation. Is this variable a string? Integer? Object? I’d have to manually check to see what type it was. This meant I’d have to have a file containing functions with type, and then I’d have to do something for them. This meant an extra 3-10 lines per function.
I decided to check out a project by Microsoft called TypeScript. What it does, is add types to everything in JavaScript. By doing this, it knows the types of variables, return types of functions, parameter types, etc. Not only does this allow it to check types and make sure everything matches, it also allows for a far better autocomplete.
I’ve been using IntelliJ Ultimate for a while. Initially I used it for Java, but with it’s outstanding support for Web Development I started using it for Node. Now not only does this support Node, it has full support for TypeScript. Autocomplete is nearly instant, and suggests only matching types. It’s far better than the native JavaScript support, and not to mention faster. Another great feature, is that as soon as I type something, it immediately compiles my .ts (TypeScript) into a .js (JavaScript) file. Here’s an example:
import Packet = require('../sockets/Packet');
class PacketAuthentication implements Packet.PacketData {
public packetName:string = 'PacketAuthentication';
public packetId:number = 10;
constructor(public id?:string) {
}
public read(packet:Packet.RawPacket):void {
this.id = packet.readString();
}
public write(packet:Packet.RawPacket):void {
packet.writeString(this.id);
}
}
module.exports = PacketAuthentication;
Then compiles into
var PacketAuthentication = (function () {
function PacketAuthentication(id) {
this.id = id;
this.packetName = 'PacketAuthentication';
this.packetId = 10;
}
PacketAuthentication.prototype.read = function (packet) {
this.id = packet.readString();
};
PacketAuthentication.prototype.write = function (packet) {
packet.writeString(this.id);
};
return PacketAuthentication;
})();
module.exports = PacketAuthentication;
The first thing you may notice, is that it removes spacing. Unfortunate, but not a terrible downside as it’s generated code. But what you should notice, is that this is nearly the exact same JavaScript I would write if I wasn’t using TypeScript (besides the (function(){})()
wrapper which is used for private variables).
But if the final result is the same as what I was writing before TypeScript, isn’t it useless? Not at all! Say I tried to change id into an Integer:
class PacketAuthentication implements Packet.PacketData {
public packetName:string = 'PacketAuthentication';
public packetId:number = 10;
constructor(public id?:number) {
}
public read(packet:Packet.RawPacket):void {
this.id = packet.readString();
}
public write(packet:Packet.RawPacket):void {
packet.writeString(this.id);
}
}
Then immediately my IDE tells me that I cannot assign id to a string, or pass an Integer to the writeString(str:string)
function. As well if I try to compile it, it simply will not compile. This is great, because it makes sure all my code is in line and correct.
Not only is this great for you, it’s great for Open Sourced projects with lots of contributors. This requires that everything is typed correctly, and lets you quickly see what’s wrong.
After spending several days converting Gitello, it’s definitely worth the extra time. There’s a much smaller chance of errors when I’m testing, and it lets me work a lot faster.