Typescript's Hollow Types
I am a big fan of typed languages. As a result I have gravitated towards
Typescript for working on personal projects. Typescript is programming language that
is a superset of JavaScript. As the name implies Typescript’s hallmark feature is
the inclusion of optional type annotations. If you add the --noImplicitAny
compiler
flag you have a reasonably type safe language with no runtime overhead when compared
to standard JavaScript.
Overall I am happy with Typescript. The type annotations allow tooling to be much better and it makes interacting with your own code type safe. My biggest problem with Typescript is it is only type safe at compile time. The compiler transpiles the code down to plain old JavaScript. If all of the code you interact with is written in Typescript, then this is not a big concern, because the compiler can parse all of the code and verify the types. For the most part this makes interacting with your own code pleasant, but it provides no protection when you interact with JavaScript.
Compiling down to JavaScript is great for the interoperability provides. It allows Typescript code to take advantage of all the projects on npm. Additionally Typescript allows you to write a typings files for JavaScript libraries. The wonderful TSD project already has typings files for most of the big projects on npm. The typings files are great for tooling, but they do a poor job of guaranteeing type safety. Because the typings files are not linked to the JavaScript they describe, it is very easy for their versions to get out of sync. If you are lucky, then the discrepancy will prevent your code from compiling. More often than not your code will compile and the problem will show up at runtime.
The separation of JavaScript and typings files makes updating dependencies much riskier. When you update to the newest version of a dependency the typings file provided by TSD is probably not going to be up to date. If there are any breaking changes to the API, then you are going to find out at runtime. This means when writing Typescript you should update your dependencies one at a time, and you should check the change logs before running the changes in production. Of course this is true for traditional typed languages like Java or C#, but unlike traditional typed languages the compiler will not help you if you miss something.