DEV Community

Cover image for The Trouble with TypeScript

The Trouble with TypeScript

Ryan Carniato on February 09, 2020

Hi my name is Ryan, and this is my first post on dev.to. I regularly write for medium.com but I wanted to give dev.to a try. I'm a big enthusiast o...
Collapse
 
juliang profile image
Julian Garamendy

This was not my experience with TypeScript at all.

I consider type annotations a way to increase the expressiveness of my code.

TS makes my refactorings easier since I know I haven't finished until the types check.

It also allows me to write fewer tests.

I tried JS without types for a small project and I got constantly stuck on silly type errors that would have been made obvious in my IDE even before saving the file.

I never felt TS slowed me down.

Collapse
 
ryansolid profile image
Ryan Carniato

From what I've read that is a lot of people's experience. Of course, I write code that has errors but they are usually easy to classify and fix. There is that 2% that aren't logical or that aren't obvious at a glance I feel TypeScript might catch. But this waiting until I'm done to run through things definitely feels slower. After a while, it actually feels that even those 2% are classifiable without heavy debugging by learning what the symptoms look like.

I've refactored large projects across multiple modules without types many times. It looks a lot like aggressively changing everything and then everything is broken. And then you work piece by piece to get things working again. I know that terrifies some people (including my developers) but my mentors did similar things, and I have found that while you can introduce bugs the process is much faster since you aren't getting hung up on those details early on. Even removing TS from the equation, I've found less experienced developer's timidness in refactor being a gigantic slowdown. And there are tests for the rest. Tests have value regardless and I feel that TS should not be a reason to write less tests since runtime is the only truth.

And that's the thing I don't think using TypeScript feels slow. I think that the process/ceremony it pushes you towards can be slower than just doing things and trying as you go. It may not be in all cases but I don't believe it's so cut and dry to be like "improves" productivity.

Collapse
 
juliang profile image
Julian Garamendy

I realise I've never worked on a large JS project (only TS). So perhaps I don't really have real-life examples to compare.

I agree the ability to refactor is more related to test coverage (of use cases) than to having types or not.

I just never felt slowed down by TypeScript, and I did when I worked on (even small) projects using only JS because I need to load the "types" or object-structures in my head instead of letting my IDE and type checker do it for me.

I never had to ask myself:

What's the shape of the object this function is expecting?

because in TS you can't get it wrong. My IDE will highlight it in red as I make a mistake.

I only add type annotations where strictly needed, I let type-inference do the work for me.
I don't spend much time writing types.

I'm not sure what's the process/ceremony you mentioned.

Cheers!

Collapse
 
trusktr profile image
Joe Pea

After the "hump" you'll find yourself more productive I think. It's just like with Vim: after using it for a while you are faster than with regular editors at text manipulation. Every day I use text fields like the one I'm typing in right now, and can tell the difference in speed. There's some Chrome extensions like Wasavi that I maybe should try. But anyways, I've done some fairly huge refactors of code bases with TypeScript (in VS Code in particular with all the refactoring tools), and I can't imagine doing the same in plain JavaScript, let alone the refactors sometimes working first try! It's wonderful.

Collapse
 
ryansolid profile image
Ryan Carniato

Yeah that's what I've been hoping for. I'm expecting the other shoe to drop for months now. And it sort of does. Like I feel fairly competent now with TypeScript. It's just the more I learn the more I'm impressed with how difficult the challenge that exists here. And while it's admirable and the community has been so helpful. There is always just the next thing.

I lived in the CoffeeScript world for a long time with no tooling after coming from C# where everything was autocompleted. It was less of a system shock than I expected. I've lived through both and they have their tradeoffs. The weird part for me is how TS is not C#. That strange ambiguity and incompleteness when approaching certain problems that are possible only because TS is JS.

Collapse
 
trusktr profile image
Joe Pea

Yeah, it is interesting how TypeScript is releasing some new type features -- that basically don't exist in any other typed language -- due to the efforts in making it possible to express JavaScript paradigms with types.

Collapse
 
trusktr profile image
Joe Pea • Edited

I'm really enjoying AssemblyScript too!

Collapse
 
jwp profile image
John Peters • Edited

Joe, kind of funny really. Webassembly must throw Javascript purists crazy. Their infrastructure is crumbling daily. Typescript from the top, Wasm from underneath. I'm not a fan of Razor, but it's ahead on challenge.

Thread Thread
 
ryansolid profile image
Ryan Carniato

Perhaps. As mentioned I'm into benchmarking. And WASM just isn't faster for DOM operations. Solid's higher level abstraction still is faster than the fastest WASM vanilla optimized hand crafted routines in JS Frameworks Benchmark. When you add a higher level abstraction on WASM it gets slower still. I'm sure it will get there some day but I think the direction of using compilation like Solid or Svelte doesn't make anyone in the wider JS community feel threatened by WASM. It's another tool. I think its more interesting when JavaScript haters don't realize that the more they accept things like TypeScript and WASM they are just playing further into the same infrastructure that legitamizes JavaScript. At some point there will be something better and it probably won't look like anything that is there right now. And it won't be because of some Type vs UnTyped mentality will be about capability and expressitivity. That's why JavaScript is still here. In those terms it is incredible. I think things can be better. JS is far from perfect but it sort of accidentally hit this sweet spot that I don't think is immediately appreciatable.

Thread Thread
 
jwp profile image
John Peters

Today, I like Javascript. But in 1990-2005, I couldn't stand it. I was forced into it due to its ubiquitous utilization. If one works the Web. Javascript is paramount.

Thread Thread
 
trusktr profile image
Joe Pea

Yeah, until WebAssembly Interface Types are out and Wasm has direct access to DOM references, it will be hard to make Wasm faster than plain JS for DOM operations. But once Interface Types are out, and Wasm can work with DOM references directly rather than needing to do it via a JavaScript bridge, we might see optimized Wasm become faster.

When the day arrives that Wasm can access DOM directly, tools like Blazor (Wasm-based DOM manipulation in .NET), RSX (JSX-like expressions for manipulating DOM from within Rust compiled to Wasm), gccx (JSX for C++), and others, will be in a great position to take advantage of it and allow developers to truly select their favorite language for working with DOM and have great performance at the same time.

AssemblyScript is TypeScript syntax, which already supports JSX, so that's going to be neat once all the existing TypeScript DOM-typed APIs work directly in Wasm.

It is currently not possible for Wasm to win against JavaScript in DOM performance, but I believe that will change.

Collapse
 
mateiadrielrafael profile image
Matei Adriel

I tried assemblyScript a few weeks ago and it has lots of problems, it feels like a prototype and until it gets out of beta I dont think I'll give it another try

Thread Thread
 
trusktr profile image
Joe Pea

What problems did you have? The main problem I can think is that it works with only a subset of the features of TS/JS, but if we stick with those features then it works well. I've been porting Three.js to AssemblyScript over at github.com/infamous/glas and so far it's been pleasing to see the ported tests pass in AssemblyScript. THe most notable changes were, so far, that we needed to modify any APIs that used object literals to instead use strictly-typed objects generated from classes. This is actually improving the type safety of the code. :)

Thread Thread
 
mateiadrielrafael profile image
Matei Adriel

I cant remember exactly the problems I had, but basically I was just porting an entity component system when I started getting random crycptic erros for no reason (and yes, I only used the supported features)

Collapse
 
jwp profile image
John Peters • Edited

And then you hit a place where you need to pass in different objects. Your first thought is loosening up the definition but then you see an example with generics and realize TypeScript uses generics way more liberally than you are used to with C++ or Java. Even cooler, their type can often be inferred which means you don't even need to annotate and everything magically works.

That is until you add a few extra levels on to, and you start coming across the inconsistencies, or the places where types can't be inferred. The other day I was helping my lead dev work through some typings on factory function that produces hooks that return CSS in JS generated classes that are a result of the style definition passed into the factory and props passed into the hook. He had something very basic and couldn't quite figure out why his types weren't working. So I sat down and started using generics to assign multiple values and creating wrappers to project types for return values. Someone how after a couple of tries I got it working for the most part. I admit I felt pretty good about myself, but the developer looked bewildered. You see he thought he was finally getting TypeScript and he had no idea what I had just done. So I spent the next half an hour explaining it. In the end, he got it, but he still didn't feel any better about it as he would have never thought about it that way. And truthfully I was in the same boat months earlier.

This is more about lack of knowledge than the goodness of Typescript.

Besides, Typescript does not preclude anything that can be done in Javascript. If it can be done in Javascript it can be done in Typescript.

Javascript's cohersion makes for programmers who are clueless to the pitfalls of type cohersion. So much so, they don't see any value to static typing at all. Including pre compile time errors they call noise.

Choosing generics over spread operators or 'any' types, or optional properties is a design decision, not a language fault. Introducing generics to newbies is costly because they will never 'just get it'. Especially when the mentor writes articles about his dislike of Typescript.

Collapse
 
markerikson profile image
Mark Erikson

If it can be done in Javascript it can be done in Typescript.

I'd have to disagree with this statement.

There's a lot of very dynamic JS behavior that is difficult or effectively impossible to describe in TS. Try looking at the React-Redux type definitions as an example.

TS definitely pushes you to alter how your APIs are defined in order to get more easily typeable code. In some ways, this is actually a good thing, but just saying "you can do any JS in TS" is too much of a hand-wave-y statement.

Collapse
 
jwp profile image
John Peters

Yes those definitions are very complex; too complex, and most likely an indication of a bad design.

I've looked into redux before and rejected the concept of separation of state concerns to other components.

The MVVM pattern kept state in the view model and there were no state issues in past 20 years. State concerns do not need to be farmed out.

Thread Thread
 
markerikson profile image
Mark Erikson

My point had nothing to do with whether Redux is a tool you should use or not.

I'm simply saying that connect is a highly dynamic JS API that was designed before TS became popular. It accepts multiple arguments, all of which are optional, the first two arguments have multiple possible overload forms, and the result is a React "higher order component" that passes those derived props to your own component. It's a very JS-centric API. Thus, trying to define typedefs for that dynamic behavior becomes harder.

In contrast, our new React-Redux hooks API is two functions:

const dispatch = useDispatch();

const todo = useSelector( (state: RootState) => state.todos[props.id]);

We didn't specifically design them that way just to work better with TypeScript, but the ability to type them easily was a factor in our consideration.

So, as I said: there is some JS behavior that is extremely hard or impossible to type correctly in TS. Therefore, TS usage pushes you to design APIs that are easier to type.

Thread Thread
 
jwp profile image
John Peters

I have seen C# apis, where one endpoint served many different things. All were later ripped out as the 'SRP' Principal was a better pattern.

I'm simply saying that connect is a highly dynamic JS API that was designed before TS became popular

I was only noticing the 'less than optimal' design of allowing an interface to accept dynamic parms. Of course it's only an opinion.

Collapse
 
jwp profile image
John Peters

The only difference in a strong type and weak type is a definition file.

The worst case is to create a type of 'any' if needed; however the Typescript definition project has 95% coverage. Not a problem for me, really.

I have yet to be stopped from using any Javascript npm package. So not sure how valid this argument is...

Collapse
 
brense profile image
Rense Bakker

The real point is... Defining types is optional in Typescript.
If you want to do it exactly right, yes some javascript behavior is hard to write types for, but whether you do that or not is a choice. Nothing in Typescript forces you to write types. You can literally grab a .js file, change the extension to .ts and run it through tsc...

Collapse
 
jwp profile image
John Peters

Excellent article on your experience with generics in Typescript. I concur that's some ugly stuff.

Collapse
 
markerikson profile image
Mark Erikson

I wrote an extended post recently on my experience learning and using TypeScript as both an app developer and a Redux library maintainer.

Summarizing, I'm totally on board with using TypeScript as an app dev, which also means I want the libraries I use to be well-typed. As a lib maintainer, dealing with type definitions can be painful, but necessary.

Ultimately, the key for using TS in an app is to be pragmatic about type usage, and be willing to accept an 80% solution rather than obsessing over 100% "perfect" type coverage.

Collapse
 
evanplaice profile image
Evan Plaice

As another lib dev I prefer not to use TS

Instead, I JSDoc comment/type all public APIs and generate the typings as a pre-publish step. It provides all the benefits of TS (ie Intellisense + inline docs + type checking) w/ none of the downsides.

IMO, typing private/internal API surfaces is a waste of time. Tests should cover logic and a good linter should cover the rest.

The main reason I use this approach is it drastically lowers the barrier-of-entry for users/contributors.

TS really does add a ton of cognitive overhead. There's no one true/correct way to type code. This leaves room for ambiguity, which leads to friction diring review. In short, who the hell wants to waste time arguing over the 'correct' way to define types?

This is less of an issue on an internal team b/c everybody should be familiar with each other's individual styles.

On OSS projects where cohesion is generally low-to-non-existent, anything that introduces friction is a no-go.

Collapse
 
ryansolid profile image
Ryan Carniato • Edited

Thanks for linking your article. That's been almost exactly my experience right down to the details of dealing with PRs and the fanaticism with typing. I think it is too easy to equate TypeScript with 100% perfect types and perhaps that is what I have the bigger issue with. I just was trying to push the boundaries with my library especially in the area of JSX and TypeScript really felt like a limitation to creativity. Which has been hard simply because it's taken creativity to prove that a precompiled Reactive library can use JSX with so many recognizable naysayers like Rich Harris, and Evan You.

I do get why better typeable APIs generally are better and I've seen the same move to simple APIs after. But definitely painful when trying to push boundaries.

In any case great article and I've distributed it to my team.

Collapse
 
the_one profile image
Roland Doda

That was a great read! Thank you. Not many people have the guts to write that they don't like TS too much because it's a HOT topic and everyone attacks them with the benefits that TS offers while no one is against those benefits. 😄

In general, programming goes back and forth in terms of "the best way to write an app". I don't want to expand on this but one example is going from OOP to Functional programming (FP) and vise-versa or SPA vs SSR. Again I see that I can elaborate on the statements above but I don't want to waste time explaining something that it's not my point.

My point is that people who come from languages like Java love TS and it makes sense because they are used to that paradigm of coding. I came to JS from Java and after some time of using it, I felt in love with JS for the "dynamic behaviour" it offers. I feel more powerful doing things with JS and I never returned to Java. Also I am now a big fun of FP and almost never use OOP. So I think there is some "truthness" on "People who go with TS don't really know how to write good JS"

However we are humans and we can't always rely on people writing good JS and the truth is that even if you are experienced enough with JS, TS does a better job on handling large codebases. I use Webstorm and the IDE offers autocompletion for JS even though it's not great. Is it true if someone says: "We write TS in order to make the IDE happy so it can help us prevent humans syntax errors or remind us we wrote a wrong code" ? I don't think it's 100% true because with TS you get errors on compilation not only inside IDE.

But let's be honest. TS offers some great benefits over pureJS and anyone benefits from them. So it's a fact that TS offers a great experience in letting you know that you did something wrong that you, as a human, could easily code it wrong with pureJS.

But let's be honest again. TS code it's not clean and there is so many examples out there that showcase TS code vs the same code in JS and of course JS wins all the time. You might argue that reading TS code can be easier because you know the typings. For example for function that receives a person argument, in TS you know exactly that the argument is an object with known properties. And you are right.

There in no doubt TS benefits are great but having to write TS code is something that I don't personally love. So I have to leave with coding in a way I don't love for the benefits I need. I think everyone agree that it would be amazing if you could write JS code and have TS benefits. Maybe people coming from Java would not love that either though (kidding.. or am I?).

JS is a very dynamic language. And TS limits the "dynamic" behaviour of JS in order to do its job.

Does that mean that TS limits you to do things that you could otherwise do with pure JS ?

YES.

But still, with workarounds and a bunch of code and experience with TS generics and diving deeper to TS becoming a better developer you can still achieve the result with the "limited JS dynamic behavior" (TS) ?

YES.

Conclusion: I am not against TS because I think everyone loves the benefits but I am against TS because I think everyone loves writing JS more than writing TS.

Since I want TS benefits in order "to be more confident with my code" (as TS docs say) I have to write TS.

NO.

The last couple of days I have been experimenting with JSdoc + TS type checking and pure JS code. And it works amazingly + offers the benefit of explaining your code not only typing it + write docs out of it. Not sure if that's really better than just using TS but currently it seems so.

I also have the option to type only the things I need to. For code that I am sure how it will behave I don't have to write typings. Even though that might seems a bad practice since you should type anything, right now I think it's an advantage. But still early to have an opinion.

Final conclusion: In order to make your code behave the way it should to and be more confident about your code and also using JS, I highly recommend this stack:

  1. XState
  2. Cypress component testing (beta)
  3. JsDoc with TS type checking + pure JS (not a strong opinion)
  4. Modularazing your code

I will write an article about this stack when I experiment a bit more with it. Hopefully it will be within this year.

Collapse
 
zelongc profile image
zelongc

This is by far the most relatable comments I can read about typescript on the internet.

As a nodeJS developer who modularazing the codebase, do functional programming with dependency injection. do my unit test properly. write component tests and e2e tests. I just cannot relate the pain points of javascript that many says over and over again.

There's some inferiority situation happening in javascript community and they think the dynamic character is (always) a language problem...

Collapse
 
ryansolid profile image
Ryan Carniato

Yes I've never had an issue writing stuff people think is controversial as I have no particular issue with defending myself and find with my ideas for Frontend Dev I need to often anyway.

In general, I think your observations are dead on. I'm not really sure what the solution is. I do think it's interesting when Vue exports different types for end-developer rather than what they use in the codebase. It makes sense but it suggests this divide is a real one anyway. Which is insane from the perspective of a true typed language and a nod to how artistic this whole endeavor is.

I haven't found JSDOC particularly pleasant anyway because for some reason it feels like more work, but that also acknowledges the fact that you weren't forced into that work when you were just iterating on the idea.

Since writing this article I've had the opportunity to continue to maintain other TS libraries including a whole platform built on top Babel (and custom Babel parser types) Honestly it is a bit of a mess sometimes and we sit there cursing TypeScript but yet we stick at it. I think as library authors it is just part of the thing.

Applications are different as you say, strict state management, robust testing etc all cover the basis. They should be there anyway even with TS. I feel it is likely in that environment the extra work is something you'd need to invest in one way or the other regardless so maybe TS isn't that bad. Like I've seen the move to TS + Prettier instead of ESLint in some cases. That is a simplification in a sense. It's also where it is least necessary.

As a library author, you can write in TS or write your definitions and call it a day. I'm starting to think that the latter might have been the better move for most libraries. It just is awkward how TS bug fixes and upgrades tend to break Semver in ways we don't want to embrace as a library author. It just adds ultimately to the unpleasantness to all those downstream.

Collapse
 
yuanhao profile image
YuanHao Chiang • Edited

TypeScript is Noisy

As in it has a higher noise to signal ratio. Less of the code you are looking at is functional.

+1 there. I've tried to give Typescript its deserved chance, everytime I feel that maybe I'm just not used to it but the feeling doesn't fade away. Reading docs in Typescript takes a lot of mental energy too.

Great article! A lot of insight and this answers a lot of the questions I had. I imagine you've learned a lot from it by working on Solid (just learned about it on this post, looks solid -- pun intended --).

Collapse
 
jwp profile image
John Peters

I felt the same way about Javascript. So much so I rejected it totally for 10 years.

Collapse
 
ryansolid profile image
Ryan Carniato

I started with QBasic and C, then got a little taste of JS in the mid to late 90s and was not impressed. Then went to University and worked professionally with "real" programming languages for about 10 years. But then through myself into JS the last 10 (5 of those being CoffeeScript). And something about it just clicked. It was so freeing. I still like C# a lot and you could use TypeScript that way. But knowing that I could be programming JavaScript is really irksome since TypeScript isn't like WASM getting me closer to the hardware. Instead it just makes doing certain things really uncomfortable. Things that I don't want to give up because I know I can. I'd rather program in C# over TypeScript any day.

Thread Thread
 
jwp profile image
John Peters

Typescript to me is just metadata for pre compile type checking saftey. It makes APIs a relic,as auto-completion just works. I get to choose when to use typing and when to ignore it. I like Typescript.

Collapse
 
albertomontalesi profile image
AlbertoM

I've been a developer for roughly 2 years, all spent using JavaScript and TypeScript. For a large project I would never go back to JavaScript, i think types make my life much easier. Admittedly we still use any in our codebase but that's also what I like about TS. Since you can just write normal JS, you are not forced to type everything, if you feel like it would take longer to apply proper types than the actual benefit you would get from doing so, you can still write plain JS or use any.

Overall I've had a great experience with TS, i had to learn it during the first few months as Junior dev and to be honest it's very easy to pick up.

Collapse
 
ryansolid profile image
Ryan Carniato

All our codebases are strict mode. But I see value for explicit any. But on the other hand I wish any just worked. It's been hard because casting to any sometimes just doesn't work too. I understand why but try to teach developers that. There isn't just an escape hatch. I think though for junior devs this is an easier pickup because they sort of don't realize what they are missing in terms of how you can approach problems with JavaScript.

Collapse
 
jwp profile image
John Peters

Typescript is great and will always outshine Javascript. It adopts Javascript and makes it dead simple for OOP folks who were around before Javascript was invented. It's the language for everybody, a bridge to sanity.

Collapse
 
luismasg profile image
Luis Ma SzGtz

This is the most simplistic statement.
"I like Typescript because I like my confort zone"
"make it dead simple for OOP folks" ... and the discussion is dead. you should have opened with that and admit it's what you know, it's your confort zone.
when all you have is a hammer everything looks like a nail.

And yet here you are doing JS to pay your rent.
Instead of staying in your old position doing cute little LINQ expression thingies.
let me guess , you also despise CSS?, UX?, DX? animated transitions?

And as for OOP being around for ages, you shot yourself in the foot there.
you're defending a pattern built in the dark ages refusing to consider that "hey , maybe we know a bit more than 60 years ago"

All i'm hearing is "I struggle with js and feel more confortable with typescript. it makes me feel all warm and fuzzy and java-y"

yes, typescript is easier for the oop folk that jumped ship and came over to js. we get that. it's a fact.
trying to convince the world the it's better then js is just being obnoxious.

Collapse
 
jwp profile image
John Peters • Edited

Your injecting odd thoughts into everything I have discussed. I don't agree with anything you've implied. It's falsey. BTW it is better for one reason alone, intellisense always works!

Collapse
 
steveblue profile image
Stephen Belovarich • Edited

🤨 I will have to agree if a project doesn’t start with TypeScript, migrating to TS can be problematic, we are all engineers and by definition that means we should be finding technological solutions to problems. Being an engineer doesn’t necessarily mean “I do what I want”.

I have run into instances where I had to refactor code to make it conform to TS compiler, but never found a use case where the refactor made the code less performant.

Perhaps instead of calling out all the issues you found with TypeScript, be more proactive and help fix those issues. That is what open source is all about, collaboration.

There is no controversy here. No “trouble”.

Collapse
 
ryansolid profile image
Ryan Carniato

I try to be heavily involved in Open Source and I have reported and joined discussions on issues. Refactoring for TS is unacceptable for Solid at this point as it is in contention for being the fastest Client UI rendering library period. So very sensitive to even smallest code changes. But that's a library.

I figured refactoring would be hard so that's why at the startup we have only started TypeScript on greenfield projects and that is the additional experience I am speaking to.

Collapse
 
steveblue profile image
Stephen Belovarich • Edited

I would like to see some concrete examples of how adopting TS would slow down rendering in Solid. Without performance metrics this is just hyperbole.

Thread Thread
 
ryansolid profile image
Ryan Carniato

Solid is all TypeScript and it works well so I feel I worded that wrong. I meant that I was unwilling to change the runtime output to better support types. Especially around JSX there have been some questionable suggestions. Most of the friction has been around declarative path based API which is there to enforce better patterns as reactivity can get out of control. Internally TypeScript still lets me use object factories where they are faster than classes. And define class interfaces without using class properties which babel can handle less than ideally. And I have benchmarks for those sort of things. Coming from the perspective of someone who benchmarks excessively it wasn't about TypeScript being slow. It's about finding the optimal JS code and then in a few places forcing TS to behave. It takes considerable effort when changes are made in certain places to test these things. So I didn't like TS changing output. But making it work without on the performance side wasn't too bad. API is a whole other thing.

Thread Thread
 
steveblue profile image
Stephen Belovarich

If you are concerned about performance then you should take a look at Closure Compiler which will change output, but is tried and true solution for optimizing JS better than any other tool.

Thread Thread
 
ryansolid profile image
Ryan Carniato

Thanks. A few of the other top tier competitors use it or used it at one point. I admittedly haven't tried it with Solid yet but it's probably worth a shot.

Collapse
 
hoichi profile image
Sergey Samokhov

I know this is an old article, but then again, it must have aged well enough for you to include it in your 2-year digest, so here are my 2 cents:

Cent 1: Libs vs Apps

I might have misread, but the experience you describe seems to be mostly as a lib author. Libs, IMHO, are different from apps in that any library worth its salt usually has much more users than it has developers, most of the bugs are very likely to be reported, and maybe even have a PR submitted for. "Given enough eyeballs, all bugs are shallow". Plus you usually have a test suite in place, so adding more tests is usually a low-friction endeavor.

Apps, on the other side, have a lot of code that isn't reused at all, and might even be called very rarery, so it can have a lot of edge cases that might break unknowingly to anybody. Also, people reporting bugs are either QA engineers, or users, so on average, bug reports have less technical details. Sure, tests might help, but I've worked in 4 shops so far, and 3 of them had very little to no tests for the client code (the fourth one has some, but not that many either). All 4 used statically typed languages though (TypeScript or ReasonML/ReScript). Whatever you can say about noisiness of TS annotations, tests seem to be more work to maintain.

And one thing apps have in spades is business logic. Types are good for domain modelling, making illegal states irrepresentable, etc. Do libs need this kind of help with modelling? I don't have a lot of experience with libs (the only lib I've published is very type-oriented: it mostly consists of API), but I have a suspicion that really good libs (or at least FE frameworks) mostly try to create simple abstractions for a lot of technical complexity. And for that kind of problems, static types in implementation can be more hindrance than help, as you have obviously noticed.

Also, I know I don't have enough experience with tests, but. One highly touted benefit of static types is ease of refactoring, and I'm not sure how the same would work with tests. You change a function signature in TS, and the type checker screams at you until you fix all the call sites. Nice and easy. (You'd have to be more careful in TS than in a language with no nullable types, but that's a minor detail.) How to get that kind of safety with tests? I bet you need a lot of coverage (probably with integration/end-to-end tests) to approach this kind of safety net. And sure, I know types won't catch everything that tests will, but again, types are cheaper.

Where I'm going with this? My point is that when authoring a lib, you probably give more thought to design upfront. And you don't refactor as willingly. So ease of refactoring, on the cheap or otherwise, isn't in high demand. And when do refactor, you have a lot of test coverage anyway, so tests are a sunk cost. With apps, the process is usually much more agile, and both ease of refactoring and maintenance cost are very important, so it's no wonder types are used everywhere, but tests are not.

Cent 2: Interface vs Implementation

I know some people think you're not man person enough when you bail out of the type system, but I think it strongly depends on whether it's interface or implementation, and I'd argue that for the latter, type safety is not as useful and doesn't matter as much. The more useful approach could be to write sane types for the interfaces, maybe write tests to make sure it works as expected—and then use whatever number of as any and @ts-ignore as you need to make it work. (In a language like ReScript, which is not a "gradually typed language" like TS, you're still free to combine static types and raw JS like this: let add: (int, int) => int = %raw(`function (a, b) { return a + b }`).)

But when it comes to interfaces, I'm with Jared Forsyth who said: "If it’s hard to type check, it’s probably hard to understand." Communicating the intent of your abstractions is probably as important as solving the problems your abstractions abstract away. So if some howto is hard to express with types, maybe it's to hard to explain at all? Sure, there are exceptions: e.g., defining targets in Stimulus is easy to grok while impossible to type check, but I'm not sure it's something to aspire to.

Conversely, if someone has to use hacks while consuming some statically typed APIs, then either the APIs are bad (or at least a bad fit for the world of static types), or your own types are convoluted, or, on a rare occasion, it's a bad case of impedance match between the API and the problem at hand. Maybe those rare occasions happen often enough with libs where you have to optimize a lot, but again, that's not much of a problem with your typical business logic code.

Collapse
 
ryansolid profile image
Ryan Carniato

I do agree with the overriding App vs Lib thing. In the article I was dealing this on 3 fronts, as a library author, then as Development Manager on frontend and backend of a Preact/GraphQL project. I will say the backend experience with TS was great. It felt easy and just worked. There were some poor types at first but it was never an obstacle.

On the client-side, it was much more painful. Part of it was just library mismatches and trying to pull of Preact Compat cleanly. And weirdness around libraries designed without TS in mind. All that being said it is a lot easier to sort of just make it work as necessary and take the value where you can. We stayed on TS for the project and the developers seemed relatively happy with it except when they got stuck.

I think I found it much more annoying in a prototyping sort of sense. Sometimes developers would be stuck, and I found it easiest to lay out the logic in simple code. With CoffeeScript my psuedo code would basically execute. We were past that with JS anyway but TS felt like the opposite end of the spectrum. In one sense it's probably better anyway. The old 10x developer leaving behind 10x the number of bugs. But my former development manager was like that and I had continued the tradition. In my career I've never seen any teams deliver that fast before or again. I'm not going to say it isn't without tradeoffs, but I find it interesting when looking at it as a matter of points along a scale. Not simply better/worse.

As a lib author, most of my friction came around functional programming APIs with paths and partial applications, and JSX. Solid uses a custom JSX compilation and typescript definitely has tied my hands more than a few times. I hit about 5 issues within my first week that have been taking years to resolve. They have addressed 2 out of the 5 in the last 2 years. Honestly I think those factors made things particularly awkward. I wouldn't expect most libraries to even hit these sort of things.

Collapse
 
spyke profile image
Anton Alexandrenok • Edited

TypeScript isn't a super set for sure. Private fields are still in beta, etc.

I'd like to see something different and designed around JS/Babel instead of C#. Flow feels abandoned and reusing types is difficult.

Collapse
 
jwp profile image
John Peters

How is reusing types difficult?

Collapse
 
spyke profile image
Anton Alexandrenok

Because of how types are stored in a single git repo.

Thread Thread
 
jwp profile image
John Peters

How is this difficult?

export lastname:string = 'default value'

Thread Thread
 
spyke profile image
Anton Alexandrenok

My comment was about how typings ecosystem works. A git repository in Flow vs. npm packages in TS.

Collapse
 
eviathan profile image
Brian Williams • Edited

"However, on the frontend, it has been nearly a disaster. "

I agree, the absolute mess I have seen people make with typescript is almost unprecedented. Its power is part of the problem. Its inherently high SNR is another.

I think you are right that it's mostly front end developers because I don't think a lot of them have had to develop some of the formal disciplines other types of developers have (not a rule just a general observation as I remember sifting through pages of mostly unnecessary thousand line files)

It feels like it's not particularly well curated with regards to style choices but I feel that is becoming normal in programming.

More and more people with very little aesthetic understanding are getting into programming. It's just a numbers game. You throw more people in and the people with a relatively rare aesthetic understanding will become more and more marginalised and the majorities influence more pervasive.

It seems like a trend to often happily trade legibility for terseness. Simplicity for often unnecessary complexity.

I cannot wait for the trend to fall back to the other side because it is getting absurd.

Collapse
 
jwp profile image
John Peters

This leads to a very strange scenario that the more complex the issue even when you go for help, communicating the intent of the code is as important as the function. When talking about possible solutions it isn't unlike people looking at modern art trying to critique the intent and the emotion of a toilet paper roll nailed to a wall. You can spend hours perfecting an elegant solution to your types without shipping any new workable code. It makes you feel really good and clever when you get it right. It is metaprogramming to the highest degree. It gets even more awkward when you are trying to use a 3rd party library who is more concerned about spending several months getting it right than getting something out that works (while in meanwhile the current types are effectively broken).

This makes little sense to me except in the context of generics. It's the same thing as saying Picassos 'Guernica' is noisy, chaotic, ugly (all true) until you discover the history behind it. Only then is its genius seen.

Collapse
 
ryansolid profile image
Ryan Carniato

Exactly. The artistic comparison is exactly what I'm getting at. Its strange for my tools to be like Picasso. I'm not particular stoked when code is that way.

Collapse
 
jwp profile image
John Peters • Edited

I spent 15 years in C#. When LINQ and Generics came out, I didn't at first see the value, why? Because I was alredy doing it without them.

Once I dug in, I couldn't live without either. But, I did have to rewire my thoughts and go through a painful learning curve.

Only then, did I start noticing code duplication based on type only. Generics extended my insight and forever changed my coding style.

Today, I have not yet had the need to use Generics in Typescript, but when I do, it'll be a no brainer.

Generics aren't for beginners nor is it for typeless programmers.

Collapse
 
juanfrank77 profile image
Juan F Gonzalez

I agree with the feeling. I started using TS because of an Angular 7 project and all it's promised features seem good but then it comes with these things where you feel you're fighting against the language or the linter is yelling at you in all these details.
The signal to noise ratio is also something that threw off pretty much all my team, it's like some lines of code for a function that get cluttered with all these decorators and things.
For me, it invoked some feelings of Deja-vu in that I sometimes felt I was reading something similar to Java or C# and got little shivers every time. Indeed I pretty much think of it as JavaScript with types and other added features but now in the project, I'm working on I'm using React PropTypes and so far so good I haven't had anything that I consider an issue. So yeah I'm one of those people that TS is not for them.
Great article, cheers!

Collapse
 
jwp profile image
John Peters • Edited

When I first learned Javascript the S/N ratio was also high plus it was very cryptic. The Javascrpt learning curve is about the same as React or Angular.

Today, I love both Typescript and Javascript. All have matured a lot in 25 years.

Collapse
 
juanfrank77 profile image
Juan F Gonzalez

It could be argued that someone coming from a backend language would find JavaScript 'noisy' and 'weird'. Several friends have told me that.

Also, the learning curve is different not only because React uses js and Angular uses ts by default, but because you can do very little with React without any extra stuff. In Angular, the minimum expression is still a boilerplate modules, routes and a styling approach.

Thread Thread
 
jwp profile image
John Peters

Yes, so many learning curves and so little time. I spent 10 years in Java, 15 in C#, 7 in Javascript and 4 in Typescript. I spoke them all fluently but was an expert of none.

Collapse
 
jwp profile image
John Peters

This is the 2020 Tech Statement of the Year.

Even Eric Elliot can't refute that point, but he tries in his Medium articles.

Eric wrote books on the greatness of Javascript before Typescript came out. He regularly casts shadows on Typescript and doesn't acknowledge that Typescript was 2 years ahead of Javascript recently. He prefers linters over built in type safety.

Collapse
 
seanmclem profile image
Seanmclem

With minimal effort and minimal extra code -you can use typescript to drastically improve readability and maintainability of your projects. Some of the problems you pointed out can be bypassed with a one-off any

Collapse
 
qm3ster profile image
Mihail Malo

I'm concurrently building a backed service in TypeScript and clientside in Svelte.
I didn't bother including TS in the clientside for the non-component files.
I find it extremely helpful, doubly so with RxJS (on the backend), where it has surprisingly good inference.
That is despite the fact that are bugs/rough edges in the typedefs though, for example when you use multicast as one of the adapters in pipe.
It obviously is a subset of JS, and that is partially the point.
You mention type inference (where you mention generics), but I must say it is actually very poor at the moment.

const arr = []
arr.push('🥔')

Oh wow, that's an Array<never>? Good to know.

Collapse
 
jove4015 profile image
Steve Weiss

"At one point getting rid of the types was actually seen as progress." - And it will be seen so again. Typing / not typing is really just a preference, not a good or bad thing - people worked without types for so long, they started to see them as a good thing again because they started to have all the problems that typing took care of for you. Now that everyone is using type annotations again, people are noticing what a PITA they can be in many other use cases. The circle never ends.

I'm just waiting for all the "cool kids" to notice how easy it was to compose objects dynamically in old code... and start trying to do that again. Imagine - you can create an object, put data on it, and send it back and forth between applications, without having to worry if the object was a string or a number? And those applications just work, because they are smart enough to detect the difference between a string and a number and don't require the developer to spell this out up front? Wow, such a language must be amazing! ... and we can introduce a new concept called magic methods, which automatically check for and assign properties on objects ... no need to write getters or setters every time you add a new property! This will happen. Just wait. The developers whose careers / reputations are ruined by hardliners who insist that only typed languages are good languages? Those are good engineers you will never get back. The human consequences are the only permanent ones.

Collapse
 
rhymes profile image
rhymes

Thanks for describing my gut feeling about TS with actual real world that goes further than toys.

I really see the point in using it as a library developer, less so as an app developer. As all things JS there's a lot of hype around it but there's also value in it. I just don't like the push towards it "just because".

TypeScript has basically dictated other technology choices

Yeah, this is a issue that I see in TS but also in Python with mypy. Theoretically you can adopt types in dynamic languages gradually but eventually everything is "omg this perfectly fine library that we used to love until 5 minutes ago doesn't have a types interface file, let's rewrite it or burden the library developers with the task of learning everything about this new ecosystem we don't fully understand either so they can build a soon to be unmaintained type file so we can finally autocomplete in Visual Studio Code and be cool" 👀

Collapse
 
jwp profile image
John Peters

What 'dictation' do you refer?

Collapse
 
jwp profile image
John Peters

TypeScript uses generics way more liberally than you are used to with C++ or Java.

This statement has no proof or value. C#, the king of generics, has it front and center as a main enhancement to compliment LINQ.

Too bad Java lagged the curve by 7 years and poorly implemented generics.

Even cooler, their type can often be inferred which means you don't even need to annotate and everything magically works.

Oh, you mean cohersion is cool?

Collapse
 
ronbravo profile image
Ronald Bravo

Interesting read. I read this article along with Eric Elliot's article, You May Not Need Typescript. I think you might find a few articles as a follow up to this one interesting:

medium.com/javascript-scene/you-mi...
medium.com/javascript-scene/the-sh...
labs.ig.com/static-typing-promise

I agree with the sentiments of this article and often feel like Typescript is an attempt to make JS more like C#. I also got this impression after having read an article on Blazor and it's promises to appeal more to the C# developers who are not fond of the frontend. It seems to me the biggest appeal to Typescript has been the auto completion from the ecosytem inside IDE's like VS Code. However, I wonder how much of the same effect can be achieved by JsDoc or perhaps something similar in the future. I once saw a presentation emphasizing to never bet against Javascript, only time will tell if this is true or not. Just my personal opinions.

Collapse
 
jwp profile image
John Peters

That is until you add a few extra levels on to, and you start coming across the inconsistencies, or the places where types can't be inferred.

What inconsistencies?

Types can never be inferred where there's no definition. But how difficult is it to define 'any'? Pretty simple to do.

Collapse
 
vsaulis profile image
Vladas Saulis

TypeScript is backed by M$. This is all you must know. M$ created the hype around it. M$ supports it. Tell me how about all M$ languages it created? All of them are silently dying. The same will be with TypeScript.

Collapse
 
eskabore profile image
Jean-Luc KABORE-TURQUIN

Hi Vladas Saulis! 👋

Welcome to the dev.to community! We're thrilled to have you here and appreciate your engagement with articles. It's great to see active participation from new users!

We would love to hear more from you about your field of expertise, whether it's JavaScript, C, or any other area you're passionate about. Our community is diverse, and we value a wide range of technical discussions and insights.

By sharing your knowledge, you can contribute to the growth and learning of fellow developers. Whether it's tutorials, code samples, or even thought-provoking discussions, your contributions will be greatly appreciated.

If you have any questions or need assistance in creating content, don't hesitate to reach out. We're here to support you on your journey of connecting with like-minded developers.

Looking forward to seeing your valuable contributions!
Happy coding! 🚀

Collapse
 
jwp profile image
John Peters • Edited

What I've witnessed with TypeScript is that 30 line CoffeeScript file is now 150 lines.

Who cares about Coffeescript? It's dead. Why bring in coffeescript comparisons?

Collapse
 
ryansolid profile image
Ryan Carniato

CoffeeScript exemplifies some of the benefits of JavaScript that tend to be lost from the TypeScript perspective. I'm not recommending using CoffeeScript right now. Simply that JavaScript has some of those characteristics and they aren't as distinctly bad as one might believe.

Collapse
 
jwp profile image
John Peters

However, on the frontend, it has been nearly a disaster.

This quantifies 1) lack of interest 2) lack of leadership 3) lack of skill and 3) new tech rejection from the Javascript world of chaos.

Collapse
 
ryansolid profile image
Ryan Carniato

Likely a lot of those things. Difficulty with 3rd party libraries with the same set of issues as well. We found we had to fix types on 3rd party libraries a number of times and did our part submitting PRs. This article is mostly a response to the universal praise TS receives. I don't think all the issues are with TS itself.

Collapse
 
jeromedeleon profile image
Jerome De Leon

I really need this right now. Thanks!

Collapse
 
jwp profile image
John Peters

change your API or add another function call to get the compiler to work the way you want, I was understandably very uncooperative.

This statement makes little sense to me. Please explain.

Collapse
 
ryansolid profile image
Ryan Carniato

I linked an example in the Material UI docs but I also hit this a couple times in Solid with JSX type casting. Like look at createStyles in this documentation TypeScript with Material UI. This function call is necessary to make TypeScript work nicely even though it is essentially a no-op and pure runtime overhead.

Collapse
 
jwp profile image
John Peters

I like your work on solid.js, the concept is great! I just did the same thing on a work project using only Json to create the component.