Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>> How does TypeScript make your "productivity drop enormously

- Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects and especially if you're not used to having a build step during development.

- Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

- Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

- Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

- Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

- Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

- Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

- The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

- It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic and coming up with meaningful abstractions which don't require arbitrary constraints to be imposed.

- Setting up TypeScript is a pain.

- Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.



I feel conflicted because just a couple years ago most comments to typescript articles were like the one above. Now that people are finally coming around and seeing the huge benefits to adopting it, comments like the one above are becoming more rare. People are still hung up on typescript not being perfect. Well perfect is the enemy of the good, and the good typescript brings is immense. Working on front end code across a 40 person team used to be a nightmare.

Dynamic typing is great when you're learning to code because compiler errors/warnings are intimidating. Once you do know how to code the compiler actually becomes a useful assistant that increases productivity. Helping you avoid dumb mistakes and make refactoring much easier.


Can confirm most of these points, but still believe TypeScript is a net positive for productivity, when you consider things like refactoring tools (VS Code). And on top of that add increased safety, less bugs and improved code quality because if you encounter something problematic you will actually dare improve it, because things are much less likely to break.


Thanks for details. Here's my response to most of them (some of this is definitely anecdotal of course).

> - Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up.

I've not personally encountered any significant compiling overhead in comparison to a regular Babel ES6 transpile. Obviously depends on project size, but there are a lot of tweaks that you can do to speed it up. I've had good luck with ts-loader.

> - Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

Are you advocating ES6 instead of TypeScript? It seems like all modern JS hits a transpilation stage before it hits the browser these days, and I see the same source mapping issues whenever I use ES6/7 with Babel + Webpack.

> - Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

Fair point, although I haven't run into this much myself.

> - Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

Not sure I follow, do you have an example?

> - Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

I mostly agree with this, which is why my strategy is just to do regular JS style schema validation where necessary, and then cast the object, rather than relying on `unknown`.

> - Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

Not sure I fully follow. If your code compiles to the point where you can use the debugger, you should have been able to use a console.log as well, right?

> - Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

If you're writing code used by others, you need to be clear about what your API expects and allows anyway, so why not be explicit about it, in a way that the compiler can enforce? An intelligent person makes mistakes, so why not see if you can give the computer the ability to catch some of those for you? And TypeScript still gives an intelligent user the ability to supersede your type restrictions if they absolutely need to.

> - It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic only.

I don't think coming up with good interface names is more difficult than good class or method names. And I'd argue that thinking about the constraints you want to impose on users is important for developing maintainable code -- whether you're doing type checking or not. And ultimately those constraints still have to exist in some manner, but without type checking the "constraint" will be the code breaking in some undefined way. By doing so you save yourself and others the mental overhead of trying to figure out what types you're dealing with at any point in your code base, or what types you're expected to pass into any given function. The initial overhead of thinking about your types pays off quickly.

> - Setting up TypeScript is a pain.

Anecdotal, but I've never had much of a problem with it (for React users, I believe you can get it for free in create-react-app now). And it's a one time setup cost anyway.


> Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects.

But you can have decreased tests because you have to test for common typing issues. A lot of my PHP tests are type-checks.

> Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

I've had this happen with a very obscure library that was partially-typed by someone (god bless their soul) but it took me only a few minutes to manually make the changes to the definition.

> Doesn't guarantee type safety at runtime

That's not the purpose of the product though. It's like complaining you can't cook a turkey in the microwave; It's true, it would be a nice, but it certainly doesn't mean microwaves are bad -- they're just for a different purpose.

> Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

Constraints? I would call it documentation. I'm sure you're users would appreciate knowing what methods your class has and what the parameters are.

> Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

Tell TypeScript to always generate the JavaScript code even on type errors and then you don't have to let it slow you down.

> The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

I think it's a good reason to avoid storing identifiers in strings which is an anti-pattern in any language. Either way, you have this problem without TypeScript. Because it doesn't solve every problem that makes a poor excuse to keep it from solving some problems.

> It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one.

I agree totally! It's never been easier to refactor and rename than with a strongly typed language. Admittedly I haven't done too much work making these big changes in TypeScript but definitely have done it with C#/Java and compared to dynamic languages the speed you can make correct changes is amazing. You can see your mistakes as you type with good tooling.

> Setting up TypeScript is a pain.

I've setup a complete modern JavaScript tool setup and setting up TypeScript is by far the easiest part of that.

> Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.

That's what async generators do. They do the same thing in other languages (just look at the disassembly). It automates creating a state machine. I don't see why anyone would want to write a state machine themselves rather than let the compiler do it for you. It's actually difficult enough that most people wouldn't do it even though it's a great programming pattern.


>> I've setup a complete modern JavaScript tool setup and setting up TypeScript is by far the easiest part of that.

I see what you mean. Maybe that is the root of the problem and the reason for TypeScript's increasing popularity. The fact that the author of the article mentioned Flow also suggests that there is a similar effect at play in his case; devs get used to the build step and since they're already spending time building JS, they might as well start building TS.

I hate bundling during development so I'm not used to waiting around when debugging. Unfortunately, most modern front-end coding approaches depend on having a bundling step during development. I guess front end development is in a bad state right now. I tried VueJS a few months ago and I was shocked at how difficult it was to find information on how to use it without the bundling step. I was able to figure it out eventually and it turned out to be a very nice framework but the information necessary to get that ideal setup was just not there.


I'm not a fan of bundling/packing obsession either, but I've come to recognize its necessity, at least at present. If you want to use any external libraries in a reliable way, or don't want to serve massive, incompatible-with-some-browsers JS files, I just don't think there's currently a way around using some sort of bundler (or, alternatively, paying the cost in slowed-down development and/or stacks of compatibility-related annoyances based on the "modern"-ness of any code you write or import). For tiny projects you may not need one, but beyond that the convenience benefits are just too great.

Every time I've tried to avoid using a bundler in development, I've either regretted it (babel/webpack/whatnot has screwed something up in prod that I didn't catch in dev), or ended up shoving the important parts of a bundler into browser plugins that roughly execute the bits of the build phase I care about in the browser when the page loads.


I feel you. I've just starting a project from scratch using modern JS development stack including TypeScript. I've previously just done by JS without any tooling at all (besides an IDE). And I have used TypeScript stand-alone without the rest of JS bundling infrastructure.

I also used to do more dynamic back-end development (PHP) but a long time now my backend work has been C#.

The future of JavaScript, probably the future of web development in general, is with a compilation/build step. Having a fully dynamic uncompiled front-end and back-end code was probably just temporary blimp. The tooling, though, already understands your concerns and has plenty of features for editing and running without noticing the build step. I could configure the TS build environment to re-load scripts on edit and I don't even have to press refresh in the browser to see the effects.

It does all feel very heavily and complicated but sometimes I have to wonder if that's just me.


Thanks for taking the time to create this detailed and helpful answer. I appreciate your work.


> Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects and especially if you're not used to having a build step during development.

It is a bit slower. There is tooling to mitigate this (filesystem watchers and such), and I've only found it to be a big stumbling block on relatively large TS projects, but you're not wrong. In almost all cases, large projects without some sort of build phase are probably pushing incompatible and/or slow code.

> Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

That's not TypeScript's fault, in my experience. It's usually because of a relatively byzantine build system that's in charge of generating sourcemaps. In fact, I've never seen sourcemap bugs that were directly caused by TS (i.e. due to Babel/Webpack misconfiguration). YMMV, of course.

> Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

This is the criticism I agree with the most. Things are improving as people start developing in TS more and shipping typings with their projects as first-class citizens, but it has a long way to go (PDFJS, looking at you).

> Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

Not unique to typescript at all. If you have a promise/async-based control flow and you integrate a library that is all about fire-and-forget with eventEmitter subscriptions, it's going to look weird to integrate. If a library you import uses a different naming scheme, or a very different pattern (e.g. heavily chained single-purpose methods vs. a more declarative style with big config objects), it's going to cause friction. In TS, most of the typing/naming friction I experience is caused by modules that would have caused friction in pure JS as well.

> Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

"This toaster doesn't make me coffee! Before I got it, I couldn't make toast or coffee. Now I just can't make coffee. What a terrible toaster!"

> Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

That's probably the single biggest benefit of using a type system.

Many folks think the biggest benefit is the compiler rejecting code which violates type rules and thus prevents bugs. I respect that, but I think that's in the second spot after "type systems make you actually think about your data transformations beforehand". This feels annoying at first, and still feels annoying when organically growing/prototyping brand new stuff in an exploratory way. But man does it pay off in a hurry: once your project becomes just "small" instead of "tiny", you'll be glad you (were forced to have) thought about those structures as a whole rather than as problems came up.

> Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

I'm not sure what you mean. If you mean "my code doesn't compile so I can't run it and printf debug", then see my response to your point above this one: while that may feel less superficially satisfying, it's saving you time and hassles in the short and medium (as opposed to immediate) term. If you mean "console.log causes the compiler to emit a warning or error", you can likely turn that off (e.g. no-console).

Regardless, I'm with you in the spirit that printf debugging should be easy and that you shouldn't be forced to use a debugger.

> The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

Sounds like an issue in the way you're writing test cases. This is just as much of a pain when refactoring highly dynamic pure JS. If something relies on stringy descriptions of objects/properties its interacting with, it's usually the last thing to be caught in a refactor and the first to produce bugs. Just say no to pointless metaprogramming.

> It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic and coming up with meaningful abstractions which don't require arbitrary constraints to be imposed.

This is the same as your above point, "Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking". It's a different paradigm than the immediately-satisfying-feeling you get from writing little bits of code and seeing them immediately "work" for a given test case. It takes some getting used to if you like the feeling of frequent, steady, incremental progress. But after trying it for awhile, I bet you'll find that you've developed features faster and feel more confident that they'll behave correctly in unexpected situations. You also may find that, if you think about the typing beforehand, when it comes time to start "thinking about logic and coming up with meaningful abstractions" you'll find those things much easier to do if you don't have to think about e.g. nullability edge cases while you do. Personally, I find that it orders my thinking into a "How do I constrain and/or generalize what the behavior must be" phase and a "now define the behavior for this specific constrained type" phase, which is very useful--especially in heavily-generalized systems like form builders or otherwise user-customizable display editors.

> Setting up TypeScript is a pain.

Sure is. It's gotten a lot better, but has a ways to go yet.

> Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.

If your TS project is big enough that you're suffering from compile times as you mentioned above, you probably use (or should be using) a build step. I've never seen a JS polyfiller that doesn't create insane code when presented with things like async generators. I'm not sure how TypeScript is different. You can tell it to output non-polyfilled JS with the '--target' config, which defaults to ultra-backwards-compatible ES3. Come to think of it, that might be why you're seeing both crazy generated code and slow compile times: https://www.typescriptlang.org/docs/handbook/compiler-option...




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: