Effective Typescript | A Non-Technical Guide


September 13, 2020


ts logo

There is a lot of hype around Typescript these days. And for good reason. It finds the perfect marriage between the dynamic nature of Javascript, as well as the tried and tested static nature of other languages.

Since giving it a try in my first Angular projects a few years ago I have absolutely fallen in love with it. Almost to the point where I will refuse to pick up a framework or a template that does not make use of it. I know this can sound a bit extreme but hear me out.

Why use Typescript

I’ll keep this short and sweet. Most of these points have been explained ad nauseam in other articles.

Fewer Bugs - By adding type definitions to your variables, classes, and functions, you provide your IDE with a way to give you feedback before runtime. This means you can catch errors during compilation, or even better - while you are coding.

Improved Autocomplete - Since your IDE now knows the types of most objects, it will only suggest relevant properties and methods for code completion. Visual Studio Code, Intellisense, and Typescript are all Microsoft’s babies, so when used all together, the developer experience is truly fantastic. Even on par with fully static languages Java or C based languages.

Self Documenting Code - I generally hold the opinion that the best comments and the best documentation are no comments and no documentation. If your code is simple, clear, and concise, it is effectively documentation in itself. Type definitions together with improved autocomplete all lend itself to self-documenting code.

Low Barrier to Entry - Essentially if you know Javascript you can get started with Typescript with virtually no hassle. Typescript is a superset of Javascript, and it compiles back down to pure Javascript before being shipped to the browser.

The main takeaway is at the cost of a little extra complexity, Typescript will drastically improve your development experience.

Effective Typescript

Have you ever been thrown into an obscure Javascript codebase, and asked to add a new feature, or maybe refactor an existing one with a short deadline looming ahead. Everything is unfamiliar and everything is overwhelming. The fear of the unknown is the greatest fear of all. We’ll… that may be a bit over dramatic but I’m sure you get what I mean.

Having to do this in a static codebase - maybe a C# project, or a Kotlin one - although still tough, would be a drastically better experience. Why? Because most of the time we can trust our IDE to tell us where any changes may have unexpected consequences in other parts of our codebase. Not so much with a Javascript project, and not necessarily with a Typescript project either.

So how can we fix this?

Here is my main approach when it come to writing effective code

All consequences to a code change should immediately be made visible.

In other words, I am constantly thinking something along the lines of - If anyone came back to this code in a few months and had to make any changes. Would their IDE or compiler immediately show them where any unintended modification would need to be made elsewhere? Be it within the same file or set of files, or potentially across boundaries if you have modified a shared database object for example.

Static languages heavily enforce this through the use of statically typed objects, for example, a Data Access Object for anything that comes from a database. Any change to the DAO will immediately reflect throughout the codebase.

Static languages also discourage any dynamic code which can’t be checked during compilation. Reflection is one such example where things can slip through the cracks, hence why it is used in very few circumstances.

Okay okay okay, enough about the joys of static code. Don’t even get me started with the headache static languages can be too. Java - I’m talking about you with all your annoying boilerplate. The real question is how can we get this level of reliability and trust from Typescript.

Type Everything

This one is relatively straight forward. See any code with the word any? Or see any unknown’s lying around? Change it to be the real type.

Another helpful tip is to get your linter to help you out here. The no-explicit-any ts/eslint rule helps out here a lot. This prevents variables with an any type not explicitly provided.

In some cases any (or preferably unknown) are necessary, but providing a comment above the any explaining why it is needed can often help with future developers potential confusion.

Use Enums or Type Literals

A common use case is trying to limit an option to only certain values. For example look at HTML inputs typed as text, number, button, checkbox etc. Although not optimal we may have conditional logic in multiple places depending on this value. Now picture adding a new input type. It becomes incredibly easy to forget to add a new case to your switch statements. We can make this a lot more maintainable by using Enums or Type Literals. Doing this allows your compiler to automatically pick up if a new case needs to be added to a switch statement.

// Using an Enum enum Colors = { Red, Blue, Green }; // Using a Type Literal type Colors = 'Red' | 'Blue' | 'Green';


Statically Typed Templates

Now here things can get a bit tricky. To try get complete type checking throughout our codebase we somehow need to ensure our templates are type checked. But HTML does not support static type checking out of the box.

Luckily most modern frameworks have found a way around this. Be it Angular with its Language Service or React with its TSX support. Vue has partial support with the Vetur extension, or you could always go the TSX route with Vue too. Template type checking is a hot topic in Vue right now so maybe something will spring out the woodwork soon.

All in all, with a few minor changes and a shift in thinking we can come close to the reliability we would find in most static language. This is the trick to effective Typescript.

Conclusion

Typescript is fantastic. It can keep your clients happy by limiting the number of bugs you ship to production. It keeps your fellow developers happy since most of your code ends up documenting itself. And it makes you happy because you can spend more time writing features and less time fixing unexpected issues.

Learn the fundamentals of effective Typescript thinking, and you’ll be reaping the rewards in no time.

Hope you enjoyed the read, and learned something while you were at it. Until next time ✌️