10 March 2019

“It’s like being able to write Scala in Javascript, but faster to compile.” That’s the first description of TypeScript that really piqued my interest, by a friend, with whom we used to write a lot of Scala at Twitter. I enjoyed the ergonomics of Scala collections, case classes, Options and Futures, and types and generics. Later, after I left Twitter, I was building another project and chose Python and Django for the backend. That project turned out OK, but coming back to Python after years of Scala, it felt ugly and less direct. When I first started using Python, I was enchanted by the simplicity and readability. But now it isn’t enough. One of Python’s slogan’s is “batteries included,” meaning that it can get you up and running quickly. If programming language were a remote controlled toy, I’d appreciate the batteries included, but now I needed not just the batteries, but also the ability to maneuver precisely and with confidence. And I feel that Typescript provides that ability for precision.

So when a couple of months ago, I was starting to build Sleek and was wondering what language to use for it, I chose TypeScript.

Here are some of my reasons.

Moving fast on a shallow learning curve

I can’t say I’m proficient in TypeScript. At all. I’m really just beginning to learn it. Still, Sleek is a startup and I want to be able to move fast and dirty if needed. I don’t have to specify precisely the type of every variable of every function signature. Every valid Javascript is also valid TypeScript which means I can use types only as needed. This gave me confidence that I wouldn’t get stuck trying to specify the types - I could just ignore it if necessary, and even let it be wrong or broken for parts which don’t matter.

I could ease my way into learning the type system, and apply only when helpful. Still a couple months in… and many of my functions and classes have some type of typing constraints on them.

Another reason that the learning curve is even shallower, is I can use TypeScript for both the frontend and the backend. This means that instead of having two learning curves, I only have one, which ultimately results in moving faster.

With startups, I feel that technical debt is not as big of an evil as with a more established a company. The reason is that in a startup, there is a big chance that what we’re building might turn out not to be needed, if customer feedback invalidates it. So we might just write off that technical debt and not have to pay it back, if we decide to scrape up the project.

Moving fast with good tooling

TypeScript is portable and works out of the box. What do I mean by that? The TypeScript team and community is really focused on providing good tools. Everything pretty much works out of the box with Visual Studio Code and all the configuration I need is in a single tsconfig.json file. This means that I can check that code into the repo and resume working the same way even if I switch computers in the future, and when another person joins the team they don’t have to configure too many things.

Visual Studio can then analyze my code and tell me when a function is not returning the right type or in general things are mismatched or missing. The great thing is that this works even when the code doesn’t have type annotations at all. The IDE can also do auto-complete which is not only helping my avoid typos, but also it is really comforting as it helps me know that I’m actually doing the right thing. That tooling also allows me to understand how other third party dependencies are structured, and jump right into their code in order to understand them.

This saves time and contributes to a overall shallower learning curve as well. All that tooling might not save too much time in typing itself in the long run, but it saves few seconds here and there which has the much more important benefit of allowing me to “stay in the flow”. When I don’t need to context switch in order to remember whether I a method is called “getAndInitializeSession” or “getOrInitializeSession”, I can keep the working memory of my brain focused on the task at hand.

That makes it really really fun to code!

Promise for the Future

One thing I enjoyed from the way we used Scala at Twitter was the use of the Future monad. That allowed us to be declarative about computation that takes a long time and to have a way to express what follows what. I missed that clarity and precision when writing Python, but with Javascript Promises bring the joy back. They go even one step further with async/await built in, which not only lets me be declarative and clear about the intent, but also to be concise and readable.

There’s also another “promise for the future” aspect of Typescript that I’m stoked about it, and that’s the community and the core development team’s progress and enthusiasm. All that fuels my hope that TypeScript will continue to improve. That’s a secret weapon for my startup. I’m long TypeScript. And by saying that I’m long, I do put my money where my mouth is, by investing my time and therefore money into it.

Culture fit

It’s hard to put my finger to exactly what it is, but I feel a good culture fit between myself and TypeScript. It allows me to be careful about the things that matter to me and not worry about things which do not. It allows me to be a craftsman and be able to produce with quality.

I expect TypeScript to help me set the engineering culture along those lines. The use of types, promises and functional programming enables a more declarative code, and easier access to monads to set the right abstractions. When doing the right thing is within reach, it will be much more likely to be done, than when it is too hard, and requires an “ad-hoc half-way bug ridden re-implementation of common lisp” to set it up. Ben Horowitz said that “all decisions were objective until the first line of code was written; after that, all decisions were emotional.”

In a startup we can make a difference not only by making something people want and satisfying a market need, but also by putting soul in our craft. Steve Jobs would force engineers at Apple and NeXT to create products with beautiful insides. This might seem like a waste of engineering and design effort into an area that the customer will never see. And especially in light of my comment above about tech debt being OK-ish at startups, it might seem that I agree that it’s a waste to have neat internals.

This couldn’t be further from the truth. When it is affordable to have neat internals, it is absolutely worth it. Even though I wasn’t there at Apple and NeXT to witness how things worked behind the scenes, I am willing to bet that the consumer facing part of the product was as polished and sensible precisely because the internals were neat as well. I am firmly convinced that patterns repeat and that nature of our world is fractal. One such pattern is that “the way you do one thing is the way you do everything”. If you’re half-assing some things, you’ll be half-assing others.

I don’t want to be half-assing Sleek, but I want to approach with care and attention both for the detail and for the big picture. If that kind of attitude resonates with you, please let me know!

One short post per week, discussing actionable mental models. Join a community of readers, who receive these posts over email.