Ask HN: Is TypeScript worth it?
I want to skip over the static typing benefits argument, because I think it is well understood that static typing is a good thing and if we could bless JavaScript with a built-in and robust typing system then I don't think many people would be against that. My issue is with the amount of extra work it places on developers, much of it the "dumb" kind of work which can eat up hours and doesn't deliver all that much value.
i) Like a framework, you are at the whim of TS devs as it gets updated (edited)
For example, a new package you install can require a new TypesScript version. Once installed, you then may need to update your source code. This can place quite a high tax on the developer, where perhaps a 10 minute change becomes hours long.
ii) Libraries are badly documented
Most libraries do not document their types, or have no examples using TypeScript. Some worst offenders: Apollo, Protobufjs. The type definitions exported by these libraries can be large and complex, and the error messages emitted by TypeScript are so long and cryptic the result is often a drawn out process of trial and error along with trawling through source files.
iii) Error messages are hard to follow
Errors are long and don't provide enough detail. They will explain a type mismatch referencing many types you may not have ever seen, and are not documented anywhere. Except for simple errors, many of them are very hard to follow to a remedy.
iv) It requires yet more transpilation
Transpilation takes time, and always adds a burden to developers. I didn't mind so much with ES6 etc because eventually many functions were included in a broad set of browsers. There doesn't seem to be much progress including TypeScript in a browser, and feels like these complicated transpilation steps could be with us for a long time.
I could probably add more to this list, but my point is that I just can't see that TypeScript is worth all this time investment and making progress so slow sometimes. Are there others that come to this conclusion? I mainly see positive posts about TypeScript.
edit: I referred to TypeScript as a framework which it isn't. However it feels similar to me in that you are at the whim of TypeScript developers and how they decide to progress with the language.
468 comments
[ 2.8 ms ] story [ 366 ms ] threadPersonally speaking, I'd say that adding another layer of abstraction onto your stack shouldn't be a dogmatic thing that you just reflexively do without considering the actual needs of a particular project. TypeScript offers some benefits for certain types of complex projects, but also some costs and problems that might not be worth dealing with for certain projects.
It's a little bit like GraphQL in a sense. That's a phenomenal idea...for a product like Facebook...but probably not actually needed for every single project.
If I take your question prima facie, then yes it's still worth it, since you seem to be dismissing the main reasons people use TypeScript, the static type benefits, and the bulk of your arguments seem to actually be about how TS can improve, not why one should throw out TS wholesale, which I personally would never do.
In other words, you're focusing on the 20% BS out of the 80% benefits. Can the 20% be improved? Of course, but I'll take 80% benefits over 0% with JS any day.
This again seems to be throwing the baby out with the bath water. Just because in some cases types can't be verified does not mean we should fully be without types at all. There are a myriad of ways to mitigate even this, Parse, Don't Validate comes to mind [0]. Type Driven Development is another way [1], as well as using runtime type checkers like Zod. This article by Kent C Dodds is a really good example of the latter, it covers everything you're talking about regarding unknown types [2].
> I would even argue that it may create a false sense of safety -- just think of the Mars satellite that crashed because some developer thought a number was in imperial units when, of course, it was in SI.
Actually, that sounds to me like just the opposite case. The dev thought it was in imperial units because they might not have known the type of said number. If the number was instead typed with `ImperialUnit unit = ...`, that issue might not have occurred. Now, if the unit value was inputted incorrectly by the programmer, that's a different issue, no amount of typing will fix a business logic typo. As well, if the satellite was fully untyped, issues like these would have occurred far more often, so taking a singular example as a damnation of an entire paradigm doesn't really work.
[0] https://news.ycombinator.com/item?id=27639890
[1] https://blog.ploeh.dk/2015/08/10/type-driven-development/
[2] https://www.epicweb.dev/fully-typed-web-apps
It's been a few years since I worked with TS professionally, but at least at the time, I saw it as 95% value, 5% BS. It provides such plainly obvious value in my eyes that I've decided I'll never write JS again unless it's a single file script or a small throwaway project/PoC.
Types do not replace other checks and tests.
I don't think the Mars satellite crashed because they trusted the type system.
> I want to skip over the static typing benefits argument, because I think it is well understood that static typing is a good thing
The OP is interesting in talking about how much of a pain in the ass TS tooling is, and... it's fair to say it's annoying.
If you accept that static types are good (and the OP explicitly said they do), then what are going to do? Basically the OP is saying, "I want static types but not the TSC compiler or ecosystem"; well... it sucks, but you're never going to get that.
The comment you're replying to is just saying: "Well, if you want static types, you gotta live with the bad stuff".
> Doesn't your counter-argument beg the question whether it is indeed 20% BS vs. 80% value?
Nope.
I do still want that value i.e. static typing, but as you point out I can't get that without the BS. And so I would rather have no typing which is the only other option (except using a different language).
This part is what is so wild to me. I simply cannot imagine throwing the baby out with the bathwater, so to speak, to throw out the entirety of static typing just because of the BS around it. In my experience, static typing is superlative, it would have to be some extremely rare situation for me to give it up.
Webpack added a lot of overhead - but if you know what came before it, it was a godsend. React added a super complex library, vs Backbone which was only a few hundred lines of code but React is totally worth it.
I'm not just trying to hark back to "the good old days", I think the ecosystem is a big improvement from where it came from but I just haven't seen enough benefit from TS for all the work you need to put in.
What I've been doing is, whenever I'm handed a random JSON blob, I throw it into a JSON->TS interface converter, paste that back into my project, and I never have to question what the heck the server is returning to me again.
There are other alternatives outside typescript and javascript, especially for serverside development.
Clientside, I've tried a lot of compile-to-JS or WASM languages and frameworks. They're just not there yet, especially when you run into some compatibility problems, not to even mention library support on the frontend. The reason I like TS for frontend is it's just JS at the end of the day, you can strip out all of the types and it works. Therefore, things like compatibility issues are simply...nonexistent.
But even so, I will say a couple of things about your arguments.
Regarding i), no, it's not a framework. But then again, I don't think that's what your argument expresses anyway. You seem to be saying "it's yet another dependency you need to keep up with". This would be correct and a valid argument. But it's unrelated with "being a framework" (which, again, it is not).
As for ii)... I'm afraid this argument could be valid for any large group you want to pick in software. Are you arguing JS libraries at large are better documented? Sounds highly dubious. From a different angle, is this a problem with the language itself or is it a problem with the libraries?
Finally, regarding iv), there is no "progress including TypeScript in a browser" and you should never have expected it. Not saying it will never happen because some person somewhere might do it, but you shouldn't expect it.
For the avoidance of doubt, the Type Annotations proposal is not actually static typing, but just a 'fancy comments' for the JS interpreter to completely ignore.
It's a problem for me - the developer. From my viewpoint I don't really care where the responsibility of bad documentation lies, only that it makes me not want to use TypeScript.
> Are you arguing JS libraries at large are better documented? Sounds highly dubious.
You can't really decouple JS libraries from TS. Most JS libraries still maintained support TS these days. My point is that many of them are still documented using JS with JS examples, and don't fully document the types that go along with all their methods.
Ok, but... what you're saying here is that, while you're not convinced by TS yourself, you expect all JS library creators to be convinced. Why should they be?
> For example, a new package you install can require a new TypesScript version. Once installed, you then may need to update your source code. This can place quite a high tax on the developer, where perhaps a 10 minute change becomes hours long.
No. It's a language compiler. You can upgrade it safely without changing a single line in your codebase. If there is a breaking change (sometimes, regarding the strictness) there's also a configuration option that lets you keep the previous behavior.
> ii) Libraries are badly documented
And so you're going to lose any and all typing as your solution? I don't understand. Undocumented but typed >>> undocumented and untyped.
> iii) Error messages are hard to follow
I disagree completely, TypeScript has helped me many times to understand what's happening and why - I mean errors that I wasn't aware of in my previously untyped JS codebase.
> iv) It requires yet more transpilation
> Transpilation takes time, and always adds a burden to developers.
Doesn't matter. Use SWC or esbuild for sub-100ms compilation times. Your CI is a long running job due to tests and lint anyways. Nobody is writing pure uncompiled JS these days - you can't use NPM libraries that way, so there's always some (Web)pack step. I haven't seen a single developer who liked having to care about browser versions and wants to go back to that - but if you add a compilation step you get that for free and can write the latest and greatest.
I am currently stuck on a very difficult issue because of a TypeScript upgrade. The upgrade caused a type mismatch with a dependency that wasn't previously an issue, and due to the lack of documentation on that dependency I am currently trawling through source code.
> And so you're going to lose any and all typing as your solution? I don't understand. Undocumented but typed >>> undocumented and untyped.
No documentation of types means going into source code to see what is there. Sometimes there could be multiple types that could be used for something, and it's not clear which should be used. Most libraries have clear docs to show me how to use a function, I'll take that any day over the uncertainty of which type may be correct in many places in my codebase.
> Doesn't matter. Use SWC or esbuild for sub-100ms compilation times. Your CI is a long running job due to tests and lint anyways. Nobody is writing pure uncompiled JS these days - you can't use NPM libraries that way, so there's always some (Web)pack step. I haven't seen a single developer who liked having to care about browser versions and wants to go back to that - but if you add a compilation step you get that for free and can write the latest and greatest.
Not arguing for no transpilation though browser compatibility isn't much of an issue these days unless you are using some super new features of the language (the reason is more about bundling the code together and jsx as far as I understand). I am arguing that each transpilation step adds yet more config that needs to be built, understood and maintained. TypeScript is probably the worst offender, almost as much work as maintaining another webpack config in your projects.
> No documentation of types means going into source code to see what is there. Sometimes there could be multiple types that could be used for something, and it's not clear which should be used.
I haven't had this experience, and I'm not super experienced with Typescript. Are you using VS Code? It typically makes it trivial to find the definitions of things I'm interacting with in the editor.
What an odd question! Even ignoring new features and better type inference that comes with new versions — once you add typescript to your project, it becomes one of its dependencies. Don't you regularly update your dependencies, just as a good practice, not to let your codebase slowly rot?
No. Update dependencies as needed for security patches (which typically avoid breaking changes), other than that never update unless there is an explicit business need.
I don't have time to spend days to weeks figuring out why upgrading Tailwind to version 3 breaks the project because of (presumably) my version of create-react-app.. do I need to eject, or copy the .ts/.tsx files over to a Vite project? Do i want to fuck around with CRACO, or editing the internal monster of a webpack config file directly?
Yes, critical security updates are important, but you shouldn't just go around upgrading major versions of other packages in your production app, without the understanding that it might be an incredibly time-consuming endeavour.
I need to upgrade it because I upgraded a dependency that needed a newer version of TypeScript to compile! And I needed that dependency to be upgraded to use a newer version of NodeJS.
It seems that the newer version of TS was more strict, and now I can't find a type from ProtobufJS that fits the code. I can update here when I understand more about this particular case, but presently my best bet is to loose some typing and autocompleting by using some unknown types :(
For me it's something like
If you’re learning JavaScript or any components of the language, you’re better off just starting with typescript (given the technical acumen up front).
It’s absolutely a no brainer, long term roi. If presented the opportunity to integrate or use now vs later.
The community is also very active, and it’s under Microsoft - and has been well maintained and quite active. Lots of libraries.
It depends. The tooling is still a barrier (even though it's gotten smaller); the cost is small for a real project, but for someone who's learning and knows nothing about the ecosystem, it could be a real obstacle to dive all the way in at once. The exception would be if you're starting with something like Deno that integrates TypeScript seamlessly. Outside of that, tools like esbuild have significantly lowered the bar vs a few years ago when you had no choice but to configure webpack + babel. But even esbuild isn't quite zero-configuration
You will outgrow those app generators, but for a learning project? There is no need for you to even see a webpack file.
The most infuriating thing is it’s almost always something a typed language would have picked up like a functions parameters changed or things removed.
No amount of unit testing or browser automation is a sufficient replacement to type checking.
Late-binding dynamically typed languages are underrated, if you can hold the mental picture of types in tour working memory, that is.
The solution to better web development is staying as far away from JavaScript as possible, not polishing what is frankly a turd.
I think it's masochism to have a Javascript project that big that benefits from strict typing.
ii) Lots of libraries are extremely well documented and typed. This is the same in any language not just for types but also for docs, capability, perf etc. This argument applies to all software everywhere so it doesn't make sense to single out TS
iii) Error messages can sometimes be hard to follow. But you get better at parsing them very quickly when they get gnarly.
iv) Transpilation is nearly always a required step anyway. Adding TS support is minimal. There are plenty of tools that do TS to JS on an order of magnitude of MS.
All decisions are tradeoffs.
What benefits does it bring (ignoring the biggest one of them all)?
TS makes it easier to maintain software across large teams by providing a mechanism to express relationships in a codebase.
They are self documenting and replace a lot of JSDoc needs (letting you focus docs on more useful info like intent, design choices, example usage, etc).
Types can also replace the majority of unit tests validating code is correct saving time on running fewer unit tests and letting devs focus on integration tests.
Lastly, I've never seen or experienced something breaking from upgrading the Typescript version in a project. Even when a TS upgrade has 'breaking changes' they never actually break anything in practice that I've seen.
I am singling out TS because although most good libraries have documentation for all of their methods, along with examples, many useful and popular libraries do not include full documentation of their types. Some hardly any at all.
Usage examples are some of the most useful piece of documentation you can have in a library, but many authors choose to show their examples in JS, in order not to be too opinionated. It is the fact that TS is not actually part of the language, and simply an add on, that I believe is the cause of many of these issues.
> What benefits does it bring (ignoring the biggest one of them all)?
I do believe it brings benefits and agree with what you have written, of course my view is that those benefits just aren't worth the effort. In my experience some of the best codebases I interacted with were neatly written and well documented JavaScript codebases - no TypeScript, whereas many of the TypeScript codebases have been very hard to understand and work with. This is by no means due to TypeScript, however it doesn't make me think that it helps in terms of making anything that much better.
I can't even remember many times TypeScript has actually prevented a bug, it's been more useful for documentation. But then I would prefer JSDoc which isn't so difficult to maintain and can still provide autocompletion for you.
> but many authors choose to show their examples in JS, in order not to be too opinionated
This is certainly true sometimes, but I don't see why it's a reason against using TypeScript? If you're calling a TypeScript API, the way you use it should look basically the same as the way you'd use it in JavaScript. You usually don't have to do anything special with the library's types unless you're getting fancy
There are exceptions- I've had a rough time fighting to get code using the styled-components library to fully typecheck, because that library gets super fancy with the way they represent things (I don't like it for that reason personally, but I know others do). But libraries like that are the exception in my experience, and if it's really that big of a drain on productivity, you can always bail out and use `any` types to skip dealing with it
For many simple libraries it's not too much of an issue, but for more complex things like Apollo (which also doesn't include much TS in their docs) it's a lot of hit and miss until you get it right.
I will also say- GraphQL almost by nature is gonna be a really hairy thing to statically type, especially on the server side. We've got an Apollo server at my company and thus far we've pretty much just punted on trying to type that part of things. Which is also more okay than might be for other things, because GQL does its own runtime validation anyway
The best choice however is to simply use a better ecosystem entirely.
IMO JVM+Kotlin is great general purpose combo, Rust is good if you don't write the sort of code that needs GC'd structures, etc. Between those two I rarely need to consider anything else.
Typescript is a wonderful tool for many situations. Typescript may not be needed for all situations. There's upfront cost to configuration and tooling. But you get type safety and automatic documentation.
In all my new non-trivial projects, I default to typescript. It has caught so many issues and saved me a lot of time. Not having it feels like driving without a rear-view mirror. But, if I'm just writing a little script, I might omit it.
Most of your (pretty good actually) critique are points to make the least-bad way of doing JavaScript even better, and I'd agree could be improved.
Others have taken notice.
"Native support" of TypeScript is done by Deno. And tight TypeScript (and other adjacent tooling) integrations with VS Code and WebStorm.
And transpilation is being worked on by various builders. Stripping types and running through esbuild or swc is fast. For typechecking part, was a proposal to have TypeScript be rewritten in Rust for performance.
We can lament that JavaScript went from being a web document enhancer to being shoehorned into a full application compilation toolchain, but the old Jquery thru Expressjs era of doing things has significant drawbacks for full sized applications/APIs/etc.
What's nice is that despite looking ugly, those shoe horns have done a pretty good job, and they all make effective tools for building useful stuff, and that stuff can be built by people who aren't very good at building stuff.
It's very much a success story that so much html/css/JavaScript is a garbage fire. They're really effective tools, up there with excel
Use your head, if you don't like TS, don't use it.
EDIT (some more thoughts):
Yes, that's not very different than upgrading to a new version of e.g. Python or Ruby on the back end. The problem is that you're seeing Typescript as "just a framework", rather than a compiler/interpreter. If you view upgrading Typescript versions the same as e.g. upgrading Python or Ruby versions, and plan for it accordingly, then you'll at least have the correct expectations regarding the scope of work, even if the actual work to do isn't any less. If a type system were integrated into Javascript itself, it would have to be optional, in order to maintain backwards compatibility with the vast untold billions of lines of Javascript that are out there. Thus, you'd have exactly the same problem. It's very difficult to add a typesystem to a language after the fact. Poor error messages are an issue with any type system that allows generics. Typescript's error messages are, at least in my experience, better than C++'s error messages. I find this remarkable, given that C++ was designed as a typed language from the beginning, and Typescript has, as one of its design constraints, strict backwards compatibility with Javascript. That's true of any programming language, Javascript included. If you're writing Java, you're at the whim of Oracle. If you're writing C#, you're at the whim of Microsoft. If you're writing C++, you're at the whim of the C++ standards committee. If you're writing Python, you're at the whim of the Python Steering Council (and you used to be at the whim of Guido Van Rossum). Every programming language has some person or committee that's in charge of it, and if you're choosing to use that language, you're implicitly accepting the decisions made by that person or committee.Even within the same project, there are times when I don't want typechecking - when I am prototyping something out and want to move fast.
And there are other times, when I want typechecking - when I am finalizing a feature implementation or doing integration with existing logic etc.
It's not a framework. It definitely is a language in its own right.
But from personal experience, the group productivity goes way up with larger codebases with many ICs working on it. Unit tests become type checks. It opens up a lot of extra bandwidth for more sophisticated functionality or better tests.
Solo IC, working on a small project, with no intention of ever writing tests - you might see TS be an overhead.
To sum up, your requirements decide whether it's worth it.
Can you think of cases where it's actually prevented a bug where that piece of code is unit tested? I have been actively monitoring for this to happen, but so far not seen it (I think I have seen it catch a couple of bugs for code that did not have unit tests).
Eg. You test code that calls a dependency that returns a bool, but your tests assume an object response
Unit tests imply assumptions about the integrations, whereas types specify those asumptions
Fwiw I'm an SDET and I regularly find bugs, on a daily basis, in a startup of around 40 people with a Python/JS web stack that TypeScript would have caught (and am pushing towards moving over to it).
My childhood not knowing about tests had a ton of wasted time trying to check that a change worked
In another project with more exotic dependencies, it has become a hassle somewhat. I've found learning the .d.ts syntax to help easily get out of a situation, but it was a learning curve I still run into sometimes.
I could document types for that module, but I don't, and instead assume types as the output of code I have that interacts with them
You do get a lot of escape hatches for different outcomes though, dependant on amount of desired effort
Dependencies are where it starts to get tricky. It also gets tough when someone else has configured TypeScript, or you need to add some complex config. I would still opt out for smaller projects because they don't quite benefit so much from TypeScript, and eventually I would expect to run into something that would eat at hours of my time for a simple change.
I will be using vanilla Javascript in my own projects for the foreseeable future.
I have not found, even in really large projects with thousands of files, that its been an impediment to anything.
My general disposition is the whole "anti build tools" moment is a bit overblown in practice, and I'm always searching for valid counter evidence of persistent issues that can't be easily overcome.
It's on you to make sure you're not misusing stuff at the boundary, but less hassle to get set up and always something you can clean up later.