Tecnología

Por qué nuestro código base es 100% TypeScript (y esperamos que algún día sea del 0%)

Una explicación de por qué nos encanta TypeScript y por qué estamos ansiosos por abandonarlo por completo.
TypeScript, TypeScript, TypeScript, TypeScript, TypeScript

Temas

This is the first in a series of technical blog posts from the Dr. B dev team. We’ve been around in various forms for a little over two years, but since this is the beginning of our technical blog, we’re starting with the basics: our programming language of choice.

We have one repo for everything we do, and here’s what it looks like:

Untitled

But why? There’s plenty of writing out there on why TypeScript is great. And it is. But its quality as a language isn’t really why we chose to go all-in on it to such an extent. It’s really because we had to (sort of).

We’re a telehealth company. Our primary patient-facing product is a platform that enables patients to quickly and cheaply get a healthcare consultation, and get medications that they need. And our first project, back in 2021, was building out a nationwide Covid vaccine waitlist (in a little over a month!). In both cases, we were building platforms hosted on the web. So, while there are plenty of backend and infrastructure requirements, what we knew for sure we needed, from the very beginning, was a website.

Websites are (usually) written with code, and almost universally, with JavaScript. (Yes, there’s webassembly, but it’s not at a point yet where it can fully eliminate the need for JavaScript). So, it was clear from very early on that we’d need to write JS. And for that, we’d probably need to learn to love NPM, and many of the tools that go along with JavaScript. TypeScript is just one of those.

So - as a team of just a handful of engineers who were building in a hurry - we decided to think about all the different things we had to commit to to get an MVP going. We started with TypeScript (which we’d bundle into JavaScript), and… we stopped there. We wanted to build our backend in AWS, with a PostgreSQL primary database, with the API served via lambda functions. All of that can be done with TypeScript and Node.js. So we decided to keep our backend in TypeScript, until we had a reason to reverse that decision. And since we were using AWS, we decided to deploy everything we used with aws-cdk - in TypeScript. So far, we’ve only really made one commitment to a programming language.

Having types consistently through the entire stack frees the development team up dramatically. We use slonik-typegen with our database client to make sure our SQL queries are strongly typed. We use an in-house CMS based on netlify-cms (now decapcms) that maps our content model to TypeScript too. Then, we use trpc with zod to make sure our API inputs and outputs are strongly typed. This all means that all parts of our stack speak the same language, and nothing falls through the cracks - the boundaries between layers are strictly enforced. We don’t need to spend hours and days and weeks debugging unexpected API response formats - the type system keeps us honest.

It’s worth noting, of course, that there are other ways to achieve most of these things, and that domain boundaries, and planning for interoperability between stacks are good things! We plan API contracts, but we don’t spend as much time as we otherwise would bikeshedding field names, camel-case vs snake-case and so on. Discrepancies are easily caught in developers’ IDEs or in code review, and conventions are enforced through our eslint config - which applies to our entire repo, with minimal maintenance overhead (...because everything is in one language). Shared conventions don’t leave as much room for petty debates, or pointless schisms, so we can focus on meaningful decisions instead. And our APIs are living entities - when they diverge from the plan, all of their consumers are aware of it quickly.

So why do we want to drop it?

There are downsides to TypeScript. There are plenty of people who think that types slow them down (and those that feel strongly enough about it to take it away from others who use their libraries). There are others that think its unsoundness makes it useless as a type system. There are languages that are terser, languages that are faster, and languages with better functional programming patterns built in. But none of that is why. In fact, in our collective opinion, TypeScript sits in a sweet spot between soundness and flexibility. In most cases, and with good practices, it can keep you safe. But it also affords you the fantastic flexibility of JavaScript. Its extremely challenging mission of making the wild west that is JavaScript type-safe has led to fantastic innovations that simply don’t exist in other typed languages. Mapped types, conditional types, and template literal types just to name a few. The TypeScript team has in fact made the type system so powerful that it (accidentally?) became Turing Complete at some point.

So why then? You might have noticed I slightly glossed over a point at the beginning, where I jumped from needing to write JavaScript, to actually writing TypeScript. We never gave JavaScript much of a shot - without any type safety, it was much too much of a risk for us. But that could change. The TypeScript team have written a really interesting proposal which would bring TypeScript-style type annotations to JavaScript. To JavaScript engines, the type annotations would just be ignored, like comments. But to developers, they can be used to type-check codebases much like TypeScript is now. This would mean we could write code “closer to the metal”. There’s a sometimes-painful transpilation/ compilation/ bundling step that there are currently a huge number of competing transpilation tools right now. The closer we can get to “just using JavaScript”, the better. Right now, we use a custom webpack setup to bundle our lambda functions. The webpack config uses SWC under the hood (and at points in the past, we’ve tried parcel, esbuild, plain old tsc, and many others). It works now, and thanks to SWC builds are fast - but it would simplify our builds a lot if we were just zipping up and deploying the src/ code directly. Until those planets align, though, we’re going to stick to TypeScript.

Temas

Suscríbase al Dr. B boletín gratuito para recibir un informe semanal sobre lo último en atención médica y consejos basados en investigaciones para mantenerse sano y mentalmente sano.