DEV Community

Cover image for The TypeScript Experience

The TypeScript Experience

lucamug on April 10, 2022

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. Readin...
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 on

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 on

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
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
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
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
etienneburdet profile image
Etienne Burdet • Edited on
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 on

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 on

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

Collapse
ecyrbe profile image
ecyrbe

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.

I beg to differ. Typescript has one of the best type inference out there. You can write almost everything but function parameters without any type annotations in typescript.

To take one of the examples, Rust requires a lot more typing. (Coming from a rust developper).

One Guy saying that he dislike typescript because he could not type it's return type because he wanted to return different types. He did not need to. Typescript would infer the return type without any issue.

Some of the issues raised come from obvious misuses of typescript.

Collapse
tbm206 profile image
Taha Ben Masaud

TS cannot infer the type of chained/composed functions; e.g. with lodash/fp/compose. That's pretty lacking if you ask me

Collapse
jwp profile image
John Peters

Lodash is not TypeScript. Any missing intellisense you expect is an issue with a bad Typedef file. It has nothing to do with Typescript.

Collapse
ecyrbe profile image
ecyrbe • Edited on

It's not an issue with typescript but with library authors of definitly typed librairies.
Take a look at fp-ts that handles chaining just well.

Collapse
rajeshroyal profile image
Rajesh Royal

When I don't knew it, I hated it. Now I do not want to go back ✌️

Collapse
jwp profile image
John Peters

Your arguments are wrong in my mind and lumping C# in the same sentence discussing 'structural typing' is highly confusing.

Your obvious hatred for TypeScript simply means you need to bar yourself from those jobs.

In the meantime TypeScript shops get stronger and have none of the issues being red flagged here.

Collapse
lucamug profile image
lucamug Author • Edited on

Thank you for the comment. I found some sources associating C# type system with the TypeScript type system, but others do not. So, until that part is clearer I will remove both C# and Java from the list, thank you for pointing it out.

I don't hate TypeScript, I actually have been a promoter of it and pushed to have it adopted in all our JavaScript code at work. I think it is a valuable asset if you have a large JavaScript project.

Here I am trying to understand why people have these experiences with TypeScript.

Does any answers reported in the post sound familiar to you? Do you think there is something that can be done to change the TypeScript experience, especially when compared with languages that use HMTS?

Collapse
peerreynders profile image
peerreynders

The comparison with C# comes up because

  • Anders Hejlsberg is the lead architect of C# and TypeScript
  • by implication:

"TypeScript began its life as an attempt to bring traditional object-oriented types to JavaScript so that the programmers at Microsoft could bring traditional object-oriented programs to the web."

That evokes the whole 2012 "ASP.NET with C#" theme. But at the very least it does imply that TypeScript was designed to feel familiar to established C# developers.

But then "TypeScript’s type system has evolved to model code written by native JavaScripters. The resulting system is powerful, interesting and messy."

… which lead to the value space (variable declaration space) and type space (type declaration space) divide - and lots of syntax to extract information from value space into type space.

const RNA_COMPLEMENT = {
  G: 'C',
  C: 'G',
  T: 'A',
  A: 'U',
} as const;

type DnaNucleotide = keyof typeof RNA_COMPLEMENT;
Enter fullscreen mode Exit fullscreen mode

Some of the tension comes from the fact that TypeScript offers more value (as in gets less in the way) as a JavaScript type linter than as a programming language.

Being able to "Just use JavaScript" (rather than having to compile it), while being able annotate types succinctly for occasional type linting should silence most criticisms. At this point JSDoc TS is seen as verbose (though @type gets close) and not all of TypeScript's features are necessarily easy to access from JSDoc/JavaScript (though that hasn't stopped projects from adopting it (most notably Preact for performance reasons)).

FYI: Deno 2.0 will skip type checking by default to improve start up performance.

I don't believe that TypeScript would have gotten as much traction as a pure type linting tool—as a programming language it brought a sense of familiarity to those with a background in statically typed languages and who were sceptical about trusting dynamically typed code.

Ideology 3:11


Type branding is sometimes used to approximate nominal typing:

Thread Thread
lucamug profile image
lucamug Author

The "Ideology" video linked is very nice.

Related to it, it would be interesting to roughly categorize people that answered the Twitter thread in

  • People that only experienced JS
  • People that experienced JS and TS
  • People that experienced JS, TS, and a statically typed language like Java, not based on the Hindley–Milner type system
  • People that experienced JS, TS, and a sound static language like Haskell, OCaml, Elm, or F# based on the Hindley–Milner type system (where type annotations are mostly optional)
Thread Thread
peerreynders profile image
peerreynders

On a side note:

A Gentle Introduction to Haskell, Version 98

"It's usually helpful to write down the type of new functions first;"

I always thought that it is useful to actually separate the type from the implementation - as opposed to the C-style conflation of both. So something like

/** @type {(string, boolean) => number} */
function sbn(s, b) {
  /* ... implementation details ... */
}
Enter fullscreen mode Exit fullscreen mode

seems perfectly reasonable - though familiarity with the mainstream, conflated syntax

function sbn(s: string, b: boolean): number {
  /* ... implementation details ... */
}
Enter fullscreen mode Exit fullscreen mode

creates a bias towards s: string "belonging together" even though they are just distinct aspects of the same positional argument:

  • s is the name the value of the positional argument is bound to
  • string is the type the positional argument is expected to be
Thread Thread
lucamug profile image
lucamug Author

"It's usually helpful to write down the type of new functions first;"

Yes, it is interesting to note that devs that use languages where type annotations are optional end up with a mindset of writing type annotation first and the implementation after.

Programming languages influence the way we find solutions.

Collapse
jwp profile image
John Peters

The Javascript community in general, did not like TypeScript. They felt their comfort zones fading away. Understandable as Assembly Language programmers did the same thing when 2nd Gen languages arrived.

Javascript folks also tend to discount Java, C## and C++ people feel TypeScript is the least problematic way to join the Javascript family.

As far as really knowing any Language is to spend around 1.5 years using it daily. Only then will they really have a feel for what it can do.

Collapse
jbartusiak profile image
Jakub Bartusiak

I absolutely love the example with bubble sort in type system. I appreciate it might be hard to learn, but it's extremely powerful, and makes big projects much easier to manage.

Collapse
almaaaaa profile image
vinz243 • Edited on

Some points are fair enough (Sometimes spend an hour just to appease the type system, The syntax can get verbose and unreadable) but other are not very well thought.

Not enough libraries come with types

This is utterly false. Nowadays every popular one has typings, and even less popular have them now. And tbf should you be using unknown and obscure packages on npm?

I don't need to have a step before running JavaScript code on Node.js, why would I add one?

This is just a useless point, because this is the point that is being discussed. Imagine : Should we ban x thing (because y) ? No I don't think so because I don't want to ban something, so why should we ban it?

Does not catch bugs

It does... More often than not. It catches most mispells and typos, and inattention issues. Which is a lot (and the most painful part of vanilla js to me)

It has flavors. I have seen Array or string[]

Comparing it to vanilla js ??

Too many different configurations.

If it wasn't the case then they would be complaining about the even greater lack of flexibility.

No real guarantees, just assurances

what does this blanket statement even means ?

It seems to me that these people want their cake and eat it too. Sure it's not perfect, and it's not THE solution that will eliminate all pain from frontend dev. It has its pros and cons as does every tool.

Collapse
masterxilo profile image
Paul Frischknecht

You write "These type-systems make sure that the code will not have errors at runtime." It should say that they make sure there won't be type errors at runtime. Many types of undesired behaviour ("errors") cannot be expressed and thus caught by a type system...

Collapse
lucamug profile image
lucamug Author

Thank you for the comment. It is difficult to express that some programming languages like Elm are not protected only from type runtime error but from all sorts of other errors. I rephrased it as:

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.

I hope it is clearer.

Collapse
masterxilo profile image
Paul Frischknecht

Yes, I love the clarity and explicitness of that! Happy Easter!

Collapse
cjsmocjsmo profile image
Charlie J Smotherman

TS is like any other dev tool we use, it depends on your use case.

On larger projects I can see how it might be of benefit, but on smaller projects its just bloat.

For me TS feels like a bandaid, an after thought, it's not part of the core of the language.

Nobody mentions flutter/dart which have a strong type system built-in from the ground up.

And there's webasembly no need for TS

Collapse
jasongodev profile image
Jason Go

The mere fact that most apps and libraries are transpiled back to javascript means that typescript is just extra work. And how many times do you see codes that have "any" as its type, for all the variables?? So it's not helping at all. Choosing between js and ts is like choosing a styleguide, another bikeshedding.

Collapse
hillin profile image
hillin

TS is a bit like C++ these days, it's complex, but most of its complexity is for lib authors (for TS, also typing authors). Daily engineering programing experience with TS is trivial 99% of the time, where the remaining 1% is you have to deal with a lib who has complex typings, like rxjs. Really it was those libs who exploit/abuse the expressivity of JS as a dynamicly typed language, and TS was only trying to type everything of them, and I'd say I'm amazed how well TS did. Now I can't imagine writing rxjs code without TS.

Another great benefit of static typing is good support of refactoring. JS simply discourages you to refactor your code because it'd too easy to mess things up. I really doubt if those TS-nay-JS-yayers have worked on a complex enough project to see this room elephant.

Collapse
brense profile image
Rense Bakker

TS has no preference for classes. TS is a superset of JS so you did learn JS, just a typesafe version of JS so you dont get as many runtime errors :)

Collapse
jwp profile image
John Peters

True. but Java, C# and C++ people are at home with the class construct.

Collapse
emil profile image
Emil

We build complex backend applications with typescript using OOP concepts and I cannot imaging doing this with plain JS