Typescript in the real world — Why and how you should use it

Yann s
Yann s
Aug 7, 2019 · 14 min read
Image for post
Image for post

Introduction

This documentation’s purpose is to expose a bit of why you should consider using it, and a lot of how you can use it. The main reason for this guide to exist, is that most guides around the web simply assume that you are already on the front seat of the hype train for Typescript. This guide assumes that you see Typescript like a father sees the new tattooed boyfriend of his daughter.

In the real world, Typescript is being used in a lot of large projects: VS Code is written in Typescript, Angular is written with and in Typescript, as well as Formik and RxJS, to name a few.

Why

Typescript reduces the number of unit tests you need to write

Image for post
Image for post

This simple function already highlights the second problem I was going to expose: JS *does* have type already whether you like it or not. But for now, my point onward: in your unit test, you need to make sure your function throws when arguments are null, undefined, strings, etc… Another test is to make sure the function always returns a proper number and not (for example) an empty value.

Image for post
Image for post

Well, with Typescript, all those tests are catered for by Typescript itself. Not only you can explicitly assert that a and b are numbers, that the result is a number, but it also allows you to set a value as “nullable” or not.

Image for post
Image for post

Typescript helps you with regression

if(typeof a != 'number' || typeof b != 'number')

Typescript doesn’t add types to your code, JavaScript is obviously already typed. It allows you to explicitly mention the type of a variable, which is fundamentally different. Some languages like Bash are effectively not typed at all, in which case, the debate would be totally different. In JavaScript, your variables are already typed, and every time you use a function, you roll the dice on whether that function expects a number, a string, and whether it can or cannot accept a null/undefined variable.

When working on a project with more than one developer, that becomes a problem. Not only issues can arise when updating dependencies, but also simply merging a PR can suddenly break an unrelated code simply because a function’s footprint slightly changes.

Typescript, when used smartly, can prevent all of that from happening with a minimal amount of work. We’ll get on to the “how” part later.

Typescript helps in discovering a project

How

Stop 1: At the beginning, was tsc, and tsc was with Typescript

Most basic usage

npm install –global typescript

If you are familiar with NPM, I invite you to install Typescript locally to a project rather than globally, but proper NPM usage is out of the scope of this article.

Let’s now create our first ts file: test.ts (Yes, I’m big on naming things).

Image for post
Image for post

Simply compile your file with tsc, it will create a test.js file next to it which you can execute.

tsc test.ts
node test.js

If you followed this guide properly all the way here (between you and me, you shouldn’t fail here already) then you should be able to admire your glorious palaver: “123”.

This is great! You are already using Typescript! What do you mean this is only JavaScript? Are you sure? Let’s try another code if you don’t believe me then:

Image for post
Image for post

If, like me, you are using VSCode, you should have already been warned against this trickster code. If not, re-run tsc on it, and it should appear!

Image for post
Image for post

See? You are writing vanilla JavaScript, yet, you have already started securing your code.

A word on config

Image for post
Image for post

If you get off the train here

The simplest way to do it, is to rely on tsconfig.json to get input/.

First change your tsconfig:

Image for post
Image for post

Use outDir and include to not have to manually compile every files

We essentially added two things: the “include” prop, which is “where your source files are” (here, src) and “outDir” which is “Where you want your output files to be” (here dist). Now, if you put test.ts in your src/ folder, alongside other ts files, simply running tsc without arguments will give you the same 1:1 structure as an output in the dist folder.

Image for post
Image for post

Next up, in order not to have to type “tsc” on every change, you can use “tsc — watch’ instead, which will update every time you save a file!

Use tsc –watch to automatically compile your changes

In the Appendix, I will explain how to make your pipeline fancier with webpack.

Stop 2: And Typescript said: “Let there be types”

Basic typing

Image for post
Image for post

Very easy, isn’t it? Simply add : to a variable to type its declaration. You can also type a function and its return value:

Image for post
Image for post

Another cool feature of TS is the notNullable check. This might seem already a bit strict for some people, so feel free to not enable it, but you might find it is actually pretty useful in the long run!

In your tsconfig :

Image for post
Image for post

Then:

Image for post
Image for post

Easy, right?

When to type

I’m going to open a short parenthesis here. A significant amount of people will try to make you set up your Typescript to be as strict as possible. Those people, comparing TS to Java or C, argue that because in C everything is typed, it’s natural for TS to type everything. Now, this is going to be a totally personal take on the subject: I strongly disagree.

Because of how dynamic and flexible JS is, typing everything can sometime end up in 3–4 lines declarations that can make your code ineligible.

Image for post
Image for post

It’s very important to consider how readable your code is. Types certainly can bloat your code in such a way that only machines would enjoy your literature. I think a lot of misunderstanding comes from the background of the JS developer, who sees types as being a developer tool to secure the code, when originally, the reason why C is typed has nothing to do with the developer; it’s for memory management. In other words, C uses types to allocate memory efficiency based on how much information you want to store in your variable. Considering that JavaScript cannot leverage this information as much, maybe it’s time to consider whether or not types are always beneficial when it comes to the developer only. Anyway, the scope of this article is not to answer that particular question. I will leave it to you to make up your own minds.

So, after this long and boring parenthesis, let’s go to what I consider to be the 80/20 split of TS efficiency.

Type at least function parameters and return value

When you write code, your building blocks are function. Typing at least the input/output of each functions, means that on the long term, with only 20% of the work, you achieve 80% of typing protection. Every time someone updates a function, you expect it to be doing roughly the same thing. If the return or the parameters change, you will get a (nice) error, telling you to update your code to not introduce any regression.

Image for post
Image for post

The reason why typing sum is not as necessary is obvious since, when you write this function, you have the whole function in view, and catching an error is way easier than catching an error done in a completely different file! And if you ended up not doing the proper thing in the function itself, consider writing unit tests to make your function more robust instead of simply relying on more types.

If you are using React, forget about Proptypes, and use Typescript to explicitly type your props and states.

Image for post
Image for post

If you get off the train here

Stop 3: And Typescript said: “Let there be a vault between projects to separate projects from projects”

Typing libraries

Image for post
Image for post

Oh, by the way! Typescript just displayed an error saying I forgot to install React! Pretty cool, huh?

Let’s install React and its typing. Bring in your terminal and type:

npm install react @types/react

Now, run your usual tsc command and hop! Typescript will tell you to review your basics of using React *wink*.

How does it work?

Stop 4: And Typescript said: “I can’t think of another title”

Advanced types

Let’s start easy with interfaces. They are a simple way to type your JSON object. It’s good practice to start your interface names with a capital case I.

Image for post
Image for post

In most code base, please avoid having interface.ts files with hundreds of them. Be smart about your data model, and keep the interface close to those generating them (ex api/ folder).

Another useful trick is the union operator. Because sometimes, a function can take or return multiple kinds of value, you can use | to expose them all.

Image for post
Image for post

If your divergence becomes more complex, Typescript also support overloading

writeFile(id: string, data: string, callback: TCallback<void>);

writeFile(id: string, data: string, options: IWriteFileOptions | string, callback: TCallback<void>);

When you define an array, you might want to explicitly specify what you can put in them:

Image for post
Image for post

Casting

Image for post
Image for post

Custom lib types

Create a definition file:

Image for post
Image for post

And then simply add the “@types/**/*” folder in the “include” of your tsconfig.

Conclusion

Don’t give up, and please take some time to take a look at the appendix, especially the additional resources which will be very useful to your new Typescript adventure!

Appendix

Tsconfig.json

Details here: https://www.typescriptlang.org/docs/handbook/compiler-options.html

noImplicitAny

You can silent the error by typing your variable to “any”.

allowJs

In case you want to be a bit more flexible, checkJs allows you to typecheck JS imported code (allowJs must be true).

noImplicitReturns

noImplicitThis

noUnusedLocals

noUnusedParameters

Strict and sibblings

React and JSX

Set that prop to ‘react’ or ‘react-native’ depending on your need.

Babel and Webpack

In order to activate it, npm install it, then in your babel config, add :

"presets": ["@babel/preset-typescript"]

If you are willing to use Webpack, consider using awesome-typescript-loader instead of the official typescript-loader. The former will have higher performance thanks to a better caching strategy.

Resources

Advanced technics:

Engineered @ Publicis Sapient

We fuse startup thinking and agile methods to help…

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store