TypeScript.WTF

The Basic Concepts

Let's answer a question from one of my favorite Twitter friends, Lachlan Campbell:

I’ve been using React near-daily since 2015, but every time I touch TypeScript everything crumbles. I’ve never sat down to actually learn anything formally, just hack around until the errors go away. I’d love a quick explanation of the basic concepts.

First off, thanks for the softball. I needed that.

The Most Basic

The most basic explanation of the most basic concept in TypeScript is contract. When you define a type on a parameter or a return value, you're specifying a contract your code needs to fulfill. So then when you call that piece of code later, you're calling it correctly. This is what's called type safety, the extent to which a language discourages type errors. Type errors are violations of that contract.

There's a preferece for typed languages because of the compilation step. In TypeScript's case, that's when it becomes JavaScript that the browser or server can run and execute. With the added type safety we can know before our code runs is something going to break.

Let's think of a simple multiply function as an example.

function multiply(x, y) {
  return x * y;
}

multiply(5, 6); // 30

multiply(5, "Fifteen"); // NaN

If we added basic types to this we can know that when we call multiply() with 'Fifteen' that we're not calling this correctly.

function multiply(x: number, y: number): number {
  return x * y;
}

The difference here between the function in plain JavaScript is the part of : number. This is a type definition. I'm defining that each parameter in this function should be a number and the return value of this function should also be a number.

Personally I like to think of this as just adding notes to my code, I've found that to be a helpful mental model.

multiply(5, "Fifteen"); // ❌ Argument of type 'string' is not assignable to parameter of type 'number'.

When we call this function with the added types, we've discovered an error and given some message on how to fix it. But now we've not only prevented a type error, but we also showed that this function will return a number later when we call it.

const answer = multiply(5, 15);

answer.toLocaleString("en", {
  style: "currency",
  currency: "USD",
}); // '$75.00'

And because the TypeScript compiler knows that answer is a number and not a boolean or an object, it can provide intelligence in directly in my editor to show all the available number methods and how to call them correctly.

It can do the same thing with arrays, classes, JSX even, third-party libraries that have type definitions.

TLDR: TypeScript provides type safety through fulfilling these contracts of type definitions and in return for adding those defintions TypeScript prevents us from potential errors and makes our tools smarter.

Crumble

In your question you also mentioned that TypeScript can cause things to crumble. This happens because the TypeScript compiler can't infer or understand what we intended to do. It's always easier to start with TypeScript than add it on later.

If you're migrating code to TypeScript, start with small sections, with React, start with your most basic components (buttons, input fields, typography, layout) as that first step. Then find which you call those updated components in, switch it a .tsx file and let the errors guide you.