Static Type Checking in GL
On GitLab's Frontend teams we use JavaScript for writing all of our FE code with EcmaScript 6 as our generation of JavaScript. We use VueJS to write our reactive features and we use webpack to compile our code with Babel and we are beginning to use code splitting. We have a lot of code written in JQuery and use many other little libraries included with Bootstrap.
We should be type checking our code. A statically types language is a language that does type checking (the process of verifying and enforcing the constraints of types) at compile-time as opposed to run-time. We do have a compile step, which is babel transforming our ES6 back into ES5, but that step does not include type checking. There are many many options available today, and I believe we should start to think about which is the best. I would like to list them all here and discuss the pros and cons of each. I will present my research thus far others can feel free to correct me where I am wrong and add in their opinions.
Flow
Flow - This is a Facebook project with an MIT license. It is not so much a full fledged language itself, but more of a superset of JavaScript with type annotations. It can also do type inferences. So you can write the follow to infer the type.
// @flow
function square(n) {
return n * n; // Error!
}
square("2");
Or you can write the follow to add a strict type annotation.
// @flow
function square(n: number): number {
return n * n;
}
square("2"); // Error!
A pro would be that it would potentially be the simplest to implement because it is the most minimal.
The cons are that it would be a potential challenge to integrate it with VueJS. Although if it is just compiled into JavaScript I do not think that our Vue code would be impacted at all.
Another con is that we are at the mercy of Facebook to support it as they come out with many other new languages. It does not have a huge community for support. However the implementation seems straight forward.
TypeScript
TypeScript - is a Microsoft project with an Apache-2.0 license. It is a full fledged language with tons of features. It has static type checking built in and looks very similar to the ES6 generation of JavaScript. It also has other advanced features like generics. It can infer types like Flow. It can also has namespaces which would benefit us greatly.
One major pro is that Vue supports it right out of the box.
Another pro is that is has a much larger community and support base. A lot of other people seem to be using it. It also has a low barrier to entry, as it is really simple.
I really like all the advanced features of TypeScript. I do not know how well it compiles down JS or how optimized that code will be. For example: does it leave out unused code like some of the other langs I am going to mention do. Like OCaml with Bucklescript is extremely beautifully optimized. Much more than a 1 to 1 conversion.
Here's some sample TypeScript.
interface Person {
firstName: string;
lastName: string;
}
function greeter(person: Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
var user = { firstName: "Jane", lastName: "User" };
document.body.innerHTML = greeter(user);
Reason
Reason which just put out a version 3, is a Facebook project which is licensed under BSD-3-Clause. It is based on OCaml and attempts to be friendlier to the writer that is familiar with JavaScript. It uses Bucklescript (mentioned above, and not a FB project, AFAIK) to compile to JavaScript. BuckleScript compiles to highly optimized JS. I really appreciate the JS that BuckleScript outputs. The goal of Reason, as I understand it, is to use the "industrial strength" of OCaml while making it easier and more friendly to learn.
To be clear: Reason is not a new language, it is a new syntax and toolchain based on OCaml.
Pros: You can write much more concise code with Reason. It is based off of OCaml which is super skookum. Because of the way that Reason is written you should see many less regression.
Cons: The license is not ideal and it's a FB project in case anyone has any problems there. It's also relatively new. With the initial release in May 2016.
Pros/Cons: Reason 3 which was release yesterday has some major syntax changes. The development seems to be mainly happening between a few developers. They have refactored 50% of messenger.com (the online facebook messenger) to Reason, and they reported a major reduction in their bugs.
Seems like a strong candidate but the learning curve is steep as it is based on OCaml and that's a completely different but awesome language.
Elm
Elm is a language which can compile to HTML, CSS, and JS licensed under BSD-3-Clause. It has it's own coding styles and way of doing things already defined. Straight from the website
Unlike hand-written JavaScript, Elm code does not produce runtime exceptions in practice. Instead, Elm uses type inference to detect problems during compilation and give friendly hints. This way problems never make it to your users. NoRedInk has 80k+ lines of Elm, and after more than a year in production, it still has not produced a single runtime exception.
A similar situation with OCaml and Reason. Because the strict type checking happens while writing code the users shouldn't see those type of bugs.
Great community and great support available.
Along with Reason and OCaml it is also a functional language and make some very strict rules, similar to OCaml. Like dividing two numbers. There is int
and float
and you can't mix them.
The big difference here being that it is a self contained unit. When you create webapps with Elm you aren't using Vue and I don't think it is meant to be used with Vue. Using it with Vue would be a challenge. It has it's own web framework which is a completely package and VERY well written. It is based on the ideas of Vue and React in that it creates 'reactive' webapps and it has it's own implementation of a virtual DOM. I wrote a few small apps with it and I have to say that it solves a lot of the problems we have, in that it 1. has fantastic performance, and 2. has it's own architecture which when followed everything is flawless. Model — the state of your application, Update — a way to update your state, View — a way to view your state as HTML. It really is a very good way of doing things.
The language is not hard to learn but is a completely new language. It is easier than Reason IMO, and if we wanted to we could do a POC. You can inject it into a page so it wouldn't have to be a refactor. It can take over a #element
. Once I started writing it I was kind of mind blown at how awesome it is. I have no idea how you would implement it with RoR or our existing arch.
OCaml
OCaml was released in 1996 making it 21 years ago. It is used all over the place in big companies like FB, Citrix, Docker and tons of others.
It is an awesome functional language with a solid learning curve. Through Bucklescript (mentioned above) written by Bloomberg you can output highly optimized JavaScript. I am sure we could use it to integrate with Vue, but I wasn't able to figure out how in the short time that I used it.
If we did not want to use Reason then we could just go straight to OCaml which Reason is built on. If we did that I believe we might be trying to solve a lot of the problems that Reason solves in the first place. But I am not 100% sure. It seems like we might be able to just use Bucketscript to compile our JS, which I know we can but how would it integrate with Vue, I am not sure. If we could pull it off I believe this would be the coolest solution. I might not be reasonable to ask everyone to learn OCaml but I believe we would could potentially get the most solid code out of this solution.
Go try a few OCaml tutorials and I think you'll love it.
Haxe
Haxe is a toolkit and language which has been around since 2005 (12 years)! It is a statically typed simple language which writes a lot like a mixture of C#/ActionScript 3/JavaScript if it had static type checking. It outputs to optimized JavaScript (it can also output Java or C#), optimized in that it won't output any unused code. It is solid as a rock and has been around forever. It has a huge community. Writing it is a joy.
Haxe and TypeScript are very similar except that Haxe has been around for much longer. It's not the cool kid anymore. It also has it's own unit testing framework if we wanted to use it. The learning curve is small and anyone from our team should be able to pick it up in about 30 minutes. It has many other fantastic features like TypeScript has like Generics and Abstracts.
It's always fun to drive the latest and greatest car, but the US Postal Service uses a Grumman LLV, because it has a lifespan of 30 years, it's economical, and it's built to last.
Conclusion
There may be other static type checkers for JS. If there are let me know and I can add them to the list.
I know that there is another issue just about Flow but I wanted to compile all of them into one list. So we can close that issue.
Also we could start to be like FB and really separate out GitLab. I am not sure if it's reasonable to say this but it might be a good idea to write our $1 million chat idea in a different FE language then the rest of GL. Maybe it's a good idea to write that in OCaml from the start. Or something else. It's the macro idea not the specific suggestion. Maybe the CI would be better suited for another tool. I don't think it's unreasonable to choose the right tool for the goal we want to achieve.
cc @gl-frontend
Very open to your opinions. Discuss.