DEV Community

Cover image for The TypeScript Experience
lucamug
lucamug

Posted on • Edited on

The TypeScript Experience

A few days ago I read a thread on Twitter where the author asked "Why wouldn’t you use TypeScript?" to people that wouldn't use TypeScript.

Reading through the answers, the perceptions of TypeScript among people that wouldn't use it are that

  • It is intimidating
  • It is an overhead
  • It makes it tedious to write code
  • It makes it harder to read code
  • It slows down development
  • It doesn't protect from runtime errors

These seem not direct critiques of static typing in general, but rather a consequence of the specific unsound static type system implemented in TypeScript, that similarly to Flow, is based on structural subtyping. This means that TypeScript’s type system allows certain operations that can’t be known at compile-time to be safe, type inference might be not correct, and it requires some level of manually-written type annotations.

In contrast, other languages like Rust, Haskell, OCaml, Elm, and F# have a sound type systems, like the HMTS (Hindley–Milner Type System), that do not require type annotations, and the types are always inferred correctly. These type-systems make sure that the code will not generate type errors at runtime. Moreover, together with other design choices, like making errors explicit in the type system ("Maybe", "Either", etc.), languages that use sound type-system are able to detect other families of runtime errors at compile time.

This is a topic already discussed at length but I wonder if there are some new perspectives.

My questions

Let me know what you think in the comment section below ❤️


Appendix - Curated overview of the Twitter thread

• Question

Looking to hear from folks who wouldn’t use TypeScript. Why wouldn’t you?

• Answers

💬

In my day job, I have to use Typescript. In my projects, I refuse.

  • Tedious writing types which 99% of the time are completely unnecessary, but required by the TypeScript compiler
  • Does not catch bugs
  • Reading code becomes much harder
  • Still needs runtime checks

💬

Because the type system is unsound and it seems to be way more complex and magical than what I would want from my type system.

💬

I spoke to a few. Found 2 types:

  • Just starting and intimidated by the wave of red
  • Experienced enough to avoid the common JavaScript pitfalls and did not get the aha moment from TypeScript

💬

Because TypeScript slows down the development of greenfield projects. It's a tool that benefits for a certain scale.

💬

Part of it was that the flexibility of JavaScript is one of its core strengths so by removing the flexibility you're removing something good.

💬

TypeScript is very useful and I find it invaluable in my day job, but it can be overkill for very small and one-off things. For other projects, there are other strongly typed compile-to-JS languages with more attractive type systems that are sometimes suitable.

💬

I'm not sure if the overhead of TypeScript is enough to justify type issues in JavaScript. Maybe in huge projects.

💬

I have tried it but had lots of problems with it. Also because some of my functions return values of different types depending on the situation. In the end, I don't get enough benefit from it. Type safety is nice to have, but I think I prefer the flexibility of JavaScript.

💬

It's hard to use a bad type system when you've used good ones in the past.

💬

I'm using it on my current project because stability is increasingly important, I wanted an excuse to learn a new thing and not get left behind, and I've been wrong before about new tools so I figured I'd give it a shot. But overall it's cost me more time than it's saved.

💬

  • Bloat (readability perhaps being the most important aspect of code)
  • Need to safeguard stuff for the runtime regardless of whatever "guarantees" I’ve gotten ahead of that time
  • Further from the metal
  • More tooling to know and maintain

💬

It slowdowns development time if you aren't used to it already. I've spent days working on things trying to type them while writing the code that could have been done in a single day.

💬

From a huge supporter of TypeScript:

  • Compile times can increase if not incremental builds or static type checking
  • "Clever" devs abusing it
  • No real guarantees, just assurances
  • A lot more code to manage
  • Some libraries have less than desirable type definitions

💬

Heavy, a bit slower, and overkill for most projects. We spend a lot of time researching good libraries to avoid writing too much code by ourselves - then why use TypeScript and write all that (mostly unnecessary) code. And most importantly - doesn't catch all bugs (not even close)!

💬

  • Too much time spent pleasing the type system.
  • Too many different configurations.
  • I don't need to have a step before running JavaScript code on Node.js, why would I add one?
  • No runtime-type checking

💬

I’ve spent more time fighting missing/broken type definitions in 3rd party libs than I care to admit.
For this reason, I won’t ever choose TS again.

💬

Cost to Benefit ratio is too high for some projects:

Benefit:

  • It's good to know the type of function argument (Especially for libraries)
  • Intellisense
  • Knowing error before runtime

Cost:

  • It's another skill to learn. TypeScript is huge
  • It has flavors. I have seen Array or string[]
  • TSConfig is another pain
  • Types can be too complex, why can't it just be a mix of primitives
  • The errors are overwhelming. I use eslint, it only warns

💬

We wrote enough Java in our careers.

💬

  • The syntax can get verbose and unreadable
  • Everything (build, test, IDE) is slower
  • Not enough libraries come with types
  • Sometimes spend an hour just to appease the type system

And that’s coming from someone (me) who is using TS on all their projects.

💬

TypeScript has to sacrifice too much to stay JS compatible. JS does not give a good dev UX by modern standards and TS does not give you a step change improvement. Try Elm!


For more answers, check the original Twitter thread.

Header illustration derived from Like emoji vector created by rawpixel.com - www.freepik.com.


🔴 Does any of these answers resonate with you and your experience❓

🔴 Do you think there is something that can be done to change the TypeScript experience, especially when compared with languages that use a sound type system❓

Let me know in the comments section below

Top comments (45)

Collapse
 
joshuakb2 profile image
Joshua Baker

I started using TypeScript when a node project of mine started to get unwieldy. It was probably less than 10,000 lines of JS code, but as requirements kept changing, the design also had to change. Major refactors were very common, and they always broke stuff because it was very difficult to keep track of everything.

TypeScript made that project so much more manageable. I use it for any project with more than 1 code file now. It doesn't prevent all runtime errors (or even all type errors), but it still prevents a ton of them. Also, the type inference is excellent and continually improving.

I don't understand why people say they're fighting the compiler so much. The types are optional! You can always just use "any" if it gets to be overkill.

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Some of the complaints listed above are - as far as I can see - very much about strictly typed languages generally.

Coming to JavaScript from strictly typed languages was liberating.... a breath of fresh air. It's like coding without the straitjacket. People should learn to work with JS as it is, instead of constantly fighting against it. TypeScript just seems like a crutch for devs not prepared to change their mindset and work in a different way.

And yes, I have used JS on large projects... and I do actually use the TS language server with the LSP plugin in SublimeText as it is faster than other language servers I've found for JS. However, I don't use any of the TS language features

Collapse
 
brense profile image
Rense Bakker

Yes I've used PHP and thought it was awesome, then I discovered that there are languages out there with less runtime errors. Btw typescript is not really a strictly typed language like Java where you are obligated to define EVERYTHING, even your function return types, which becomes a massive PITA. Typescript uses type inference, which offers the same typesafety, but less headache:

  function notComparableToJava(returnType: 'string' | 'int') {
    if (returnType === 'string') {
      return "Hello World!"
    } else if (returnType === 'int') {
      return 42
    }
    // no else clause, return type can be undefined
  }
Enter fullscreen mode Exit fullscreen mode
(local function) notComparableToJava(returnType: 'string' | 'int'): "Hello World!" | 42 | undefined
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tqbit profile image
tq-bit • Edited

Tbh, I don't mind either of them. I started with JS and will always use it for my personal projects, but TS has its benefits on shared codebases. Or when I come back to a project later on.

Yeah, sure, types do create overhead and ARE tedious to write.

With every con, in my opinion, there's something to be gained though.

Types in TS (or JS with JSDoc):

  • make my code verbose, but prevent me from reading through several layers of code abstraction
  • make by IDE argue every other time, thereby forcing me to think my functions and classes through
  • take time to write, but drastically reduce time I spend in the debugger

For team projects, there's another benefit to be gained:

Your stuff doesn't suddenly crash when another dev fiddled around or updated a NPM module with a breaking change (yes, that actually happens)

I think experts call this 'Robust Code'. I just wouldn't want to spend an hour cursing at my debugging-terminal if it can be prevented by 15 minutes of typing my module.

Collapse
 
miketalbot profile image
Mike Talbot ⭐

My editor folds away types in JSDoc, it can't do that for Typescript because - not comments... JSDoc also has documentation, not just a list of types. It's my choice

Collapse
 
brense profile image
Rense Bakker

Typescript also has documentation typescriptlang.org/docs

Collapse
 
dinsmoredesign profile image
Derek D

I was a huge TS naysayer; I agreed with every single one of those bullet points. Now, I find going back to JS projects very difficult.

I think the big problem with TS is some people take it too far. Yes, it definitely can be harder to read if you use inline types, types that are named the same as your classes or you feel the need to annotate absolutely everything instead of rely on type inference where it makes sense. Things like generics can also be super confusing to new TS devs and oftentimes, they are unneeded.

If you write TS sensibly, it can be a HUGE boost to your productivity because all of the code is nicely documented by the types themselves. If makes onboarding devs 10,000x easier, as long as they understand TS decently. I don't feel like I make many type errors that TS catches and, in some cases, I find it annoying when I have to deal with things the compiler says is a problem, but simply isn't... But I recently had to go back and update a project I built years ago in Vue with plain JS and I found it a complete nightmare to figure out what half the logic was doing because there were no annotations and the inference of the IDE just threw "any" types all around.

Even on the smallest projects, I use TS now and don't really think there's a single instance I'd consider writing regular JS unless it was just a plain HTML/CSS/JS project that adding a compile step would be overkill for.

Collapse
 
jwp profile image
John Peters

Agreed

Collapse
 
reubence profile image
Reuben Rapose

Wow, I thought I was the only one not enjoying the experience of Typescript. I started developing a product in React 5 months ago. Back then typescript really felt like the right thing for a newbie because it helped me avoid tons of minor errors. But overtime as I became better at JS as a whole, i started getting frustrated with typing definitions of every variable and eventually (in order to meet my delivery date) I even started completely skipping type checks by filling in "any" as the type.

Soon after I started to wonder what is the point of typescript if I'm barely even using it at this point. I thought I was just following bad programming practices. But after reading this post & comments I'm convinced typescript is not at all a necessity for every damn project.

Collapse
 
jwp profile image
John Peters

Many Javascript folks tend to lean too deep into Typedefs when they only need to write functions that tell input and output types.

Doing that allows intellisense for every function.

Collapse
 
reubence profile image
Reuben Rapose

Could you help me out with some examples?

Collapse
 
brense profile image
Rense Bakker

Its a small minority of coding cowboys, usually former backend devs who switched to javascript at some point. You can tell usually by the comparison with Java. Type defs used to be a problem but not since 2020, all maintained libs on npm either have built-in type defs or they're available through @types. Often these coding cowboys are very passionate about some unmaintained lib that hasnt been updated for 9 years and is full of security exploits. Typescript is a superset of JavaScript, so people complaining how the syntax of JavaScript is better than Typescript, you can just immediately ignore 😛

Collapse
 
reharik profile image
Raif Harik

I don't know if it's an issue with ts or tooling or what, but 9 times out 10 when there is an error it is super difficult to understand what type is expected and/or how you have failed to satisfy it. There is often so many layers of inheritance, extension or composition that knowing what you need to provide can eat away your day. And sanity. Even when it is a simple type and a simple violation the error message is super verbose.
After about 9 months if full time ts dev, I can get around just fine and can decode errors pretty well, but it wasn't easy and definitely wasn't pretty.
My other major complaint is that while you get all the verbosity of a strongly typed language, you get none of the good parts. E.g. introspection/reflection, metadata about the types you are using. Instead of helping me to write intelligent tools, I find it prevents me from writing reusable code by requiring use of generics, which in c# I found to be one of the greatest assets, but in ts I find to be a black hole.

Collapse
 
brense profile image
Rense Bakker

If you hover a function or variable in visual studio code it will tell you exactly what type it expects:

(method) RTCPeerConnection.addIceCandidate(candidate?: RTCIceCandidateInit | undefined): Promise<void> (+1 overload)
Enter fullscreen mode Exit fullscreen mode

not sure what you mean by it being super verbose, when i have a type violation i see something like this which tells me exactly what i did wrong:

Argument of type '{ bla: string; }' is not assignable to parameter of type 'RTCIceCandidateInit'.
  Object literal may only specify known properties, and 'bla' does not exist in type 'RTCIceCandidateInit'.
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jwp profile image
John Peters

The number of layers of inheritance do not need to be deep. Chances are high the deep inheritance aspect is bad implementation.

Collapse
 
etienneburdet profile image
Etienne Burdet • Edited
import { OldComponent as _OldComponent } from 'components';
const OldComponent: any = _OldComponent;
Enter fullscreen mode Exit fullscreen mode

I won't lie, there are things I really like with TS, but I wish I could spend less time making the compiler happy.

If someone wants to make a sound type system for ES6+, I'm all-in for it… 😂

Collapse
 
brense profile image
Rense Bakker

Why on gods earth would you do that?

Collapse
 
etienneburdet profile image
Etienne Burdet

Because OldComponent is not typed (and we don't want to type it now), so it creates problem with types of children, spread props etc.

Thread Thread
 
brense profile image
Rense Bakker

Not sure how that is possible? Afaik if you can import your untyped js code like that, typescript is going to infer types from it as well... If it's an untyped module and type inference is not possible for some reason, you can use something like this:

// components.d.ts
declare module 'components' {
  export const OldComponent:any
  // or just give it a proper type asuming its a react component?
  export const OldComponent:() => JSX.Element
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
corscheid profile image
Corey Scheideman • Edited

Ahh I remember this Twitter thread. I laughed so hard at the Bubble Sort type 🤣 Part of me was like... WHY... and part of me was like holy sh1t that is ... impressive - I did not know this was possible in TypeScript.

Collapse
 
patoi profile image
István Pató • Edited

We've rewritten a large code base to JavaScript + JSDoc from TypeScript:
SPA, frontend, Vue.js v2 + TS ➡️ Svelte + JS + JSDoc: half size of "runtime" JS and source code, three time faster build

  • smaller source code
  • readable code
  • increased maintainability
  • booting new developers is faster
  • more developers available, because you don't need to know TS
  • fewer dependencies: less breaking change, less vulnerability
  • less tooling

youtu.be/xLDVfBUgD8U