My short journey from TypeScript to JavaScript with JSDoc and back

Author
Igor Afanasov
Publication Date
21 July 2020

My short journey from TypeScript to JavaScript with JSDoc and back

TL;DR: Type checking with JSDoc is mature enough for production projects. TypeScript with Babel is lightning fast and mature, leaving no tech reason for me to use pure JavaScript.

I always was and still am a TypeScript fan. Good static code checkers can spot lots of errors before compilation and save tons of time. Especially on the most difficult bugs — typos. Recently I’ve encountered articles here and there describing how JSDoc and the ecosystem around it became mature. I built the impression that JS + JSDoc became close to what TypeScript offers. You can set a variable type even with generics. 

variable-type-generics

Full example on github

The same goes for function arguments. Destructed argument typing looks even nicer.

desctructed-arg

Example on github.

Especially compared with TypeScript.

compared

See github.

JSDoc also allows us to define our own types, use generics, import types from separate files, and define enums. VS Code IntelliSense supports JSDoc as well.

Why don’t I give it a try?

The Opportunity

And here the proper opportunity opened. I joined a big project team and received a task to implement two small and simple AWS Lambdas. One just writes the data into DynamoDB based on request parameters with tiny logic. The other one reads this data, does some calculations, and provides a result.

As always with production software, I started with TypeScript. I set up the scripts for development, unit tests, and production builds using the TypeScript compiler. I was surprised by the compilation time. With pure JavaScript, there is no compilation and the updated Lambda is ready to test right after the source code is saved. With TypeScript for one tiny function, it took 2 seconds. Not much, I agree. If the result is the same, why would you pay more? I got a feeling it could be worth trying JS + JSDoc. Still, I was not sure. The first code review comment convinced me:

“Hey! It’s nice to see you are trying TypeScript. In our team, about 20 people know JavaScript, and only a few familiar with TypeScript. It could be a challenge to support. May we consider JavaScript?”

If you are wondering what the difficulty is with learning TypeScript when JavaScript is already mastered to some extent, I can tell you this team was truly multidisciplinary with folks having deep knowledge in one discipline and broad knowledge of other disciplines. They do whatever is useful for the project even when there is no work for their main discipline. This team was heavy on DevOps who know JavaScript. TypeScript is not a popular language among the DevOps community. That meant the TypeScript project could have been difficult to support for the team. 

JSDoc in Practice

The learning curve is gentle. The simple JSDoc cheat sheet is enough. It covers almost all scenarios. 

There is some clumsiness related to type definition imports from separate files. One may find several syntax versions. Development tools usually support some, but not all. 

I’ve put together an example of the syntax and import style that works well with VSCode below. The first file defines the Address type, and the second file implements the typing. 

vscode

typing

We finished this project with JSDoc and it did the job of ensuring proper types well enough. VSCode support was very handy. Development experience is nearly the same as TypeScript except for annoying typing imports. Now I know that for such a small project JS + JSDoc could be enough and could save a bit of time. But by accident, I got acquainted with a better solution.

Babel + TypeScript is lightning fast

Once upon a time, I crossed the roads with Babel. Back then it was a JavaScript that transpiles modern JavaScript to JavaScript compatible with modern browsers. Take your time to comprehend it. Everyone loves this definition (can you read my sarcasm?). 

With the appearance of TypeScript, Babel disappeared from my radar. It was possible to use them together though. You could have compiled TypeScript to JavaScript and then used Babel. There was no point in it. It just adds complexity and increases the compilation time.

Nowadays, Babel made a great step forward. It can transpile Typescript directly to Browser-Compatible Javascript. And Babel does it lightning fast. Even faster than the TypeScript compiler.

The TypeScript compiler does a lot of work during the compilation. It scans for type definitions, including within node_modules, and ensures your code is used correctly. In comparison to it, Babel doesn’t care about types, has superior caching, and single-file emit architecture. At the end of the day, it’s just way faster.

You will ask: why do I need a TypeScript without type checking? Well, do you really need to check all the types during each compilation? I bet in most cases the IDE already would warn you before the compilation. Checking types once before the commit or during the PR build may be enough for your team.

In summary, when you use Babel as a compiler for development and TypeScript for type checking in the quality gate, you archive fast development and ensure a centralized type checking.

Wait, it seems too good to be true. What are downsides?

Babel 7 was announced with the shortlist of limitations regarding TypeScript:

  • No namespaces
    • With modern import/export I have never needed namespaces.
  • Bracket style type-assertion/cast syntax regardless of when JSX is enabled (i.e. writing <Foo>x won’t work even in .ts files if JSX support is turned on, but you can instead write x as Foo).
    • Instead of `<Foo>x` we need to get used to `x as Foo` syntax in case of using JSX.
  • Legacy-style import/export syntax (i.e. import foo = require(…) and export = foo)
    • I haven’t ever seen it in my life in commercial software.

Also, one of the most popular questions regarding TypeScript support by Babel is TypeScript decorators. And to solve it you might find a plugin as well. Babel is quite a long time on the scene and it is quite popular. The ecosystem is mature and you may find lots of useful plugins which is a great bonus.

Ok, I’m ready to give it a try. What should I do?

Microsoft (you might have heard of this company before — they are the creators of TypeScript) provided us with a great small TypeScript Babel Starter repo. It contains everything set up to use TypeScript with Babel and instructions on how to add Babel into the existing project. If you need to make it work with a rollup or webpack, you will find the guidance there as well.

Conclusion

  • JSDoc is mature and could be used for real-world software. It would make the project code more reliable.
  • The TypeScript makes great friends with Babel. Babel is lightning fast. Almost like there is no compiling happening at all. There is a big community around it. Lots of plugins as well. If you face some trouble you will not be alone and would find help.
  • If you are starting a new project, I strongly advise trying TypeScript with Babel. If you are working on an existing TypeScript project, adding Babel is an idea worth considering.

Let our expertise complement yours

Leave your details below and we'll be in touch soon.