Or: Use TypeScript without Transpiling
As a colleague and I were planning a new project, we realized there were pain points in our existing projects that we wished very much to resolve (particularly an Express API written in TypeScript that pre-dated both of our start dates at the company).
The biggest pain points we wanted to resolve were:
- TypeScript's transpilation time slowing development
- TypeScript's transpilation obscuring stack traces
Resolving these TypeScript pain points was NOT trivial because we didn't want to simply throw it out. TypeScript provides enhancements to developer experience that we didn’t want to lose, including:
- documentation of properties and methods of complex objects
- test coverage that all declared types successfully pass type-checking (meaning, among other things, that your documentation correctly describes your code)
- autocompletion hints inline in the editor
- type mismatches surface inline in most editors, which helps catch bugs before you've even hit "Save"
So, how does this change resolve the pain points?
Pain Point: Transpilation Slows Development
Pain Point: Transpilation Obscuring Stack Traces
While it's possible to resolve this while still transpiling your code by enabling source map support, removing transpilation resolves the issue completely and doesn't involve relying on either userland source map support or experimental Node core support.
The flip side of this is that TypeScript does have support for some things that are not available in the version of Node we currently use (Node 12) – notably, the optional chaining operator
?., which I’m sad to lose until we upgrade to a new version of Node.
Conclusions and Recommendations
We concluded that this resolution resolved all of the pain points we identified. At this time, the only new possible pain points that we've noticed are:
- Writing complex type declarations with JSDoc annotations (and translating existing TypeScript type declarations to JSDoc annotations) is not as well-documented as doing it in TypeScript; so far, the few times this has come-up, it's been a good signal that simplifying our code was a better solution.
Note that for frontend projects, the tradeoffs are not the same:
- Frontend projects will always transpile, even without TypeScript (for the foreseeable future, at least), so the headaches caused by transpilation cannot be avoided.
- Source map support in browsers is more mature than it is in Node, so stack traces in frontend projects can be more easily configured to use source maps.
As a result, we have adopted this resolution, and recommend that new backend projects at our company do the same. This is the pattern I will use for all of my personal projects, as well.
Here's a bare-bones
After adding that to your project, add TypeScript as a dev-dependency using
npm install -D typescript and run
tsc to check your project for TypeScript errors.