TypeScriptWhy and when to use TypeScript


Introduction

If you find the arguments for type systems persuasive in general, then you'll be happy with TypeScript.

It brings many of the advantages of type system (safety, readability, improved tooling) to the JavaScript ecosystem. It also suffers from some of the drawbacks of type systems (added complexity and incompleteness).

Remarks

The merits of typed vs. untyped languages have been debated for decades. Arguments for static types include:

  1. Safety: type systems allow many errors to be caught early, without running the code. TypeScript can be configured to allow fewer programming errors
  2. Readability: explicit types make code easier for humans to understand. As Fred Brooks wrote, "Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious."
  3. Tooling: type systems make code easier for computers to understand. This allows tools like IDEs and linters to be more powerful.
  4. Performance: type systems make code run faster by reducing the need for runtime type checking.

Because TypeScript's output is independent of its types, TypeScript has no impact on performance. The argument for using TypeScript rests on the other three advantages.

Arguments against type systems include:

  1. Added complexity: type systems can be more complex than the language runtime that they describe. Higher order functions can be easy to implement correctly but difficult to type. Dealing with type definitions creates additional barriers to using external libraries.
  2. Added verbosity: type annotations can add boilerplate to your code, making the underlying logic harder to follow.
  3. Slower iteration: by introducing a build step, TypeScript slows down the edit/save/reload cycle.
  4. Incompleteness: A type system cannot be both sound and complete. There are correct programs which TypeScript does not allow. And programs which TypeScript accepts can still contain bugs. A type system doesn't alleviate the need for testing. If you use TypeScript, you may have to wait longer to use new ECMAScript language features.

TypeScript offers some ways to address all of these issues:

  1. Added complexity. If typing part of a program is too difficult, TypeScript can be largely disabled using an opaque any type. The same is true for external modules.
  2. Added verbosity. This can partially be addressed through type aliases and TypeScript's ability to infer types. Writing clear code is as much an art as a science: remove too many type annotations and the code may no longer be clear to human readers.
  3. Slower iteration: A build step is relatively common in modern JS development and TypeScript already integrates with most build tools. And if TypeScript catches an error early, it can save you an entire iteration cycle!
  4. Incompleteness. While this problem cannot be completely solved, TypeScript has been able to capture more and more expressive JavaScript patterns over time. Recent examples include the addition of mapped types in TypeScript 2.1 and mixins in 2.2.

The arguments for and against type systems in general apply equally well to TypeScript. Using TypeScript increases the overhead to starting a new project. But over time, as the project increases in size and gains more contributors, the hope is that the pros of using it (safety, readability, tooling) become stronger and outweigh the cons. This is reflected in TypeScript's motto: "JavaScript that scales."