DEV Community

Cover image for Is TypeScript worth it?
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

Is TypeScript worth it?

Written by Paul Cowan✏️

Before I start, I would like the jury to know that I am, for the most part, a TypeScript fan. It is my primary programming language for frontend React projects and for any backend Node work that I do. I am on board, but I do have some nagging doubts that I would like to discuss in this post. I have programmed in nothing but TypeScript for at least three years now across numerous contracts, so TypeScript is doing something right or is fulfilling a need.

TypeScript has defied some insurmountable odds to become mainstream in the realm of frontend programming. TypeScript is no.7 in this post that lists the most in-demand programming languages.

Whether you use TypeScript or not, the following practices should be in place for any software team irrespective of size:

  • Well written unit tests should cover as much of the production code as is deemed reasonable
  • Pair programming– an extra set of eyes can catch a lot more than syntactical errors
  • A good peer review process — proper peer reviews catch many bugs that a machine cannot
  • Use of a linter such as eslint

TypeScript can add an extra layer of safety on top of these, but I feel it’s last by a country mile in the list of in-demand programming languages.

LogRocket Free Trial Banner

TypeScript is not a sound type system

I think this is possibly the main problem with the current incarnation of TypeScript but, first of all, let me define what sound and unsound type systems are.

Soundness

A sound type system is one that ensures your program does not get into invalid states. For example, if an expression’s static type is string, at runtime, you are guaranteed only to get a string when you evaluate it.

In a sound type system, you should never be in the position at compile-time OR RUNTIME where the expression does not match the expected type.

There are, of course, degrees of soundness and soundness is open to interpretation. TypeScript is sound to a certain degree and catches the type errors below:

// Type 'string' is not assignable to type 'number'
const increment = (i: number): number => { return i + "1"; }

// Argument of type '"98765432"' is not assignable to parameter of type 'number'.
const countdown: number = increment("98765432");

Unsoundness

Typescript is entirely upfront about the fact that 100% soundness is not a goal and non-goal no.3 on the list of non-goals of TypeScript clearly states:

Apply a sound or “provably correct” type system. Instead, strike a balance between correctness and productivity.

What this means is that there is no guarantee that a variable has a defined type during runtime. I can illustrate this with the following somewhat contrived example:

interface A {
    x: number;
}

let a: A = {x: 3}
let b: {x: number | string} = a; 
b.x = "unsound";
let x: number = a.x; // unsound

a.x.toFixed(0); // WTF is it?

The above code is unsound because a.x is known to be a number from the A interface. Unfortunately, after some reassignment shenanigans, it ends up as a string, and the following code compiles but errors at runtime.

Unfortunately, the expression shown here compiles without any error:

a.x.toFixed(0);

I think this is possibly the biggest problem with TypeScript, as soundness is not a goal. I still encounter many runtime errors that are not flagged by the tsc compiler that would be if TypeScript had a sound system. TypeScript has one foot in both the sound and unsound camp with this approach. This halfway house approach is enforced with the any type, that I’ll mention later.

I still have to write just as many tests, and I find this frustrating. When I first started getting TypeScript, I wrongly concluded that I could stop the drudgery of writing so many unit tests.

TypeScript challenges the status quo, claiming that lowering the cognitive overhead of using types is more important than type soundness.

I understand why TypesScript has gone down this path, and there is an argument that states that the adoption of TypeScript would not have been as high if a sound type system is 100% guaranteed. This is disproved as the dart language is finally gaining popularity as Flutter is now widely used. Soundness is a goal of the dart language which is discussed here.

Unsoundness and the various ways that TypeScript exposes an escape hatch out of strict typing make it less effective and unfortunately make it better than nothing right now. My wish is that, as TypeScript gains popularity, more compiler options are available to enable power users to strive for 100% soundness.

TypeScript does not guarantee any runtime type checking

Runtime type checking is not one of TypeScript ‘s goals, so this wish will probably never happen. Runtime type checking would be beneficial when dealing with JSON payloads returned from API calls, for example. A whole category of errors and many unit tests would not need to exist if we could control this at the type level.

We cannot guarantee anything at runtime so this might happen:

const getFullName = async (): string => {
  const person: AxiosResponse = await api();

  //response.name.fullName may result in undefined at runtime
  return response.name.fullName
}

There are some supporting libraries like io-ts, which is great but can mean you have to duplicate your models.

The dreaded any type and strictness option

The any type means just that, and the compiler allows any operation or assignment.

TypeScript tends to work well for small things, but there is a tendency for people to any type anything that takes longer than one minute. I recently worked on an Angular project and saw a lot of code like this:

export class Person {
 public _id: any;
 public name: any;
 public icon: any;

TypeScript is letting you forget the type system.

You can blast the types out of anything with an any cast:

("oh my goodness" as any).ToFixed(1); // remember what I said about soundness?

The strict compiler option enables the following compiler settings which do make things more sound:

  • --strictNullChecks
  • --noImplicitAny
  • --noImplicitThis
  • --alwaysStrict

There is also the eslint rule @typescript-eslint/no-explicit-any.

The proliferation of any can destroy soundness in your typing.

Conclusion

I must reiterate that I am a TypeScript fan, I use it on my day to day job, but I do feel it is coming up short and the hype is not entirely justified. Airbnb claims 38% of bugs could have been prevented by TypeScript. I am very skeptical of this precise percentage. TypeScript is not turbocharging existing good practices. I still have to write just as many tests. You could argue, I am writing more code, and I might have to write type tests. I am still getting unexpected runtime errors.

TypeScript offers above basic type checking, but soundness and runtime type checking are not goals, and this leaves TypeScript in an unfortunate halfway house with one foot in a better world and one where we currently are.

Where TypeScript shines is with good IDE support, like vscode, where we get visual feedback if we mistype something.

Typescript error in VS Code
TypeScript error in vscode

Refactoring is also enhanced with TypeScript and breaks in code (such as changes in method signatures) are instantly identified when running the TypeScript compiler against the modified code.

TypeScript has enabled good type checking and is definitely better than no type checker or just plain eslint but I feel it could do much more and sufficient compiler options could be exposed to those of us who want much more.


Plug: LogRocket, a DVR for web apps

 
LogRocket Dashboard Free Trial Banner
 
LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
Try it for free.


The post Is TypeScript worth it? appeared first on LogRocket Blog.

Discussion (23)

Collapse
xcs profile image
XCS • Edited on

Is TypeScript worth it?

Yes.
End of discussion.

There are many other answers to the same question here: dev.to/bettercodingacademy/typescr...

Collapse
ionline247 profile image
Matthew Bramer

I literally was in the same room as a team of 5 debug Typescript for 4 hours, just to get it up and running on 1 box. There's some perks, but there are some pitfalls. It's not for every project. Large, complex apps existed prior to TS and will continue to do so. It's not a zero-sum game.

Collapse
jwp profile image
John Peters

Why did debug session take so long?

Thread Thread
ionline247 profile image
Matthew Bramer

Not too sure, as I was working on another project; being productive. 😉

Thread Thread
xcs profile image
XCS • Edited on

I think a lot of people think swithing to TypeScript can be done overnight with the press of a button. People forget that you still need to learn a new programming language. But once you do, it's always worth using it for projects larger than single file scripts, especially when there are multiple people working on the same project.

Thread Thread
ionline247 profile image
Matthew Bramer

I've been writing JS for over a decade. Still haven't needed typescript and the latest, large project I worked on, Typescript would have been a major inhibitor to velocity. Not bc itself, but due to the team's seniority.

Thread Thread
jwp profile image
John Peters • Edited on

When compilers first came out all the folks who wrote assembly language said "We been writing assembly forever, we don't need no stinking "language".

When C++ came out many C people refused to use it.

When Java came out, non-OOP people saw no value.

When Functional programming styles were introduced in C# via the static extension methods, many established C# shops refused to use them. Why? "They chew up memory"

When LINQ came out, many didn't use it for years. Once they figured it out, they can't live without it.

When RXjs came out, many said it's too complex I'll stick with events.

When REST came out, SOAP people were skeptical.

When LESS and SASS came out, the expert CSS folks didn't need or want to adopt it.

When React came out, Angular people panned it.

When JavaScript came out OOP folks laughed at it's design. Some refused to use it (choosing server side for rendering). Once client side MVC was introduced, JavaScript became ubiquitous.

Each new generation of "things" ultimately won adopters. Most were successful, some were not (Silverlight). This means that each company adopts different "things" and if we want to work there we must learn what they have.

Typescript is only a inhibitor to velocity when the people using it have to learn it. After that, it can be argued to be faster than JavaScript due to auto-completion and catching type error before run time.

Typescript is a wonderful fit for OOP crowd as it is no different than other languages such as C# and Java in concept. Angular and React support it and many companies want Typescript people right now. Yes there is now a fractured Typescript vs JavaScript world. Why not know both?

Thread Thread
jwp profile image
John Peters

You are right, any new thing used in any project is ultimately a minimum of 6 months to get fluent and feel comfortable. We often say it take 1.5 years to become a real Subject Matter Expert. Most of this is easy "if you have the time". On the other hand, it's a guaranteed toxic environment when there's no time.

Thread Thread
ionline247 profile image
Matthew Bramer

A lot of what you said is subjective.

Typescript is great for devs that don't really want to learn JS and stick with an OOP paradigm. That's what I've seen from my experience and those devs will flourish. The question of: Why not both? Because type checking and the cost benefit is not worth it at all. The tooling that exists already is good enough and easy to implement. Why not learn JS and move away from the C#/Java-esque syntax?

I do see value in a JSDocs mashup with Typescript being of value. That way there's less C# in the JS written and you get some feedback from the type checker. That's a solid implementation imo.

medium.com/@trukrs/type-safe-javas...

Collapse
worc profile image
worc

it depends. you don't need typescript if you're approaching the problem differently. prop types and flow and named parameters with defaults all contribute to cutting down on type errors without having to add another language/transpile step to your project.

the cost of managing (preventing?) interfaces and classes inheriting from each other exists. the cost of finding and maintaining valid types for your project exists. there's cost in just integrating typescript projects with the rest of the frontend development ecosystem.

you don't want typescript if the added complexity isn't bringing you enough added utility.

Collapse
jwp profile image
John Peters • Edited on

Actually the 'added complexity' is subjective. Why? Because, to some of us, there is zero added complexity when using Typescript.

Auto completion at code-time catches bugs, rather than at run time. Bypassing Typescript says 1) For each runtime bug press F12 for debug mode 2) Select console and read the message 3) Go back to editor and put in a change 4) Save which reloads code 5) Repeat for every bug

Thread Thread
ionline247 profile image
Matthew Bramer

There is absolutely an overhead, cognitive load if you will, to typescript. There's tooling in the JS ecosystem that catches bugs as you write code that work really well. Typescript has its place, but it shouldn't be a default for JS.

Thread Thread
jwp profile image
John Peters

For me, Typescript will always be the default tool, it's simply a better choice.

Thread Thread
ionline247 profile image
Matthew Bramer

For me, it doesn't provide enough value yet for me to implement it in any code base I'm working on.

Thread Thread
worc profile image
worc

the added complexity isn't subjective though. typescript increases the complexity of the language so it can handle typing and type errors. it's right in the name.

and, man, i don't know, if your workflow includes refreshing blindly and hoping that you've fixed your bug, typescript isn't going to save you. you need a much deeper level of re-education and tooling than just a type system to get rid of that bad habit.

Thread Thread
ionline247 profile image
Matthew Bramer

You're clearly wrong if you think I need a re-education of how to debug software. I don't run into these issues with the language because I've never relied on the falsehoods you're touting and learned the language without using training wheels.

Thread Thread
worc profile image
worc

that's an interesting paper, for sure. but it does kind of undermine the original point of saying typescript is less error-prone than javascript, right? neither typescript or javascript (or coffeescript for that matter) were associated with a higher or lower number of bug fix commits.

Collapse
manuelojeda profile image
Manuel Ojeda

We need and prevent any type issue from our side as devs. Is more easly to incur on a typing mistake from us instead caming from the API or the user side.

Collapse
itsjzt profile image
Saurabh Sharma

Our team has been using typescript for a year now, reasons why we use typescript:

  • auto complete (biggest reason I think)
  • life is too short for one off errors
Collapse
juancarlospaco profile image
Juan Carlos

I come from CoffeeScript, that is kinda dead now.
I tried TypeScript, observed the same that this post mentions.
I tried some Python-to-JavaScript compilers, they were not good at all.
I tried Nim, solved my problems, including TypeScript ones.
:)

Collapse
0xdonut profile image
Mr F.

I've seen you mention a few times in here, it likes nice but there is a really tiny community and ecosystem for web apps, unless you can point out otherwise

Collapse
juancarlospaco profile image
Juan Carlos

It is a language to work with other languages too, I use it for Python,
I am part of the Python community, and find it searching for alternatives to Cython,
you can "import" C and JS libs and use them from Nim,
it is Python-like syntax instead of JavaScript-like so that may or may not be a disadvantage,
besides that no one forces you to abandon JS community.

But JavaScript community is biggest on the whole world anyways,
all communities are tiny communities compared to JavaScripts...
🤷‍♀️

Collapse
layzee profile image
Lars Gyrup Brink Nielsen

Asserts gets us some of the way for runtime type checking.