Hacker News new | past | comments | ask | show | jobs | submit login

Hi there! I work on the TypeScript team and I respect your feedback. Of course I do think TypeScript is worth it, and I'll try to address some of the points you've raised with my thoughts.

i. Dependency management is indeed frustrating. TypeScript doesn't create a new major version for every more-advanced check. In cases where inference might improve or new analyses are added, we run the risk of affecting existing builds. My best advice on this front is to lock to a specific minor version of TS.

ii. My anecdotal experience is that library documentation could indeed be better; however, that's been the case with JavaScript libraries regardless of types.

iii. Our error messages need to get better - I'm in full agreement with you. Often a concrete repro is a good way to get us thinking. Our error reporting system can often take shortcuts to provide a good error message when we recognize a pattern.

iv. Compilation can be a burden from tooling overhead. For the front-end, it is usually less of a pain since tools like esbuild and swc are making these so much faster and seamless (assuming you're bundling anyway - which is likely if you use npm). For a platform like Node.js, it is admittedly still a bit annoying. You can still use those tools, or you can even use TypeScript for type-checking `.js` files with JSDoc. Long-term, we've been investigating ways to bring type annotations to JavaScript itself and checked by TypeScript - but that might be years away.

I know that these points might not give you back the time you spent working on these issues - but maybe they'll help avoid the same frustrations in the future.

If you have any other thoughts or want to dig into specifics, feel free to reach out at Daniel <dot> MyLastName at Microsoft <dot-com>.




Thanks for your work, TS saves me time every day. I was saying something similar to the op 3-4 years ago but really cannot picture working without some kind of type safety in JS now.


> TS saves me time every day.

Hmm, not my experience. I do TS for years now and still today I'm spending more time on fighting/pleasing TS compared to the actual code.

JS with all its node_modules dependencies is a complete nightmare to get the typing right. I regularly have to change good solid code to please TS, but at the same time TS often doesn't complain when the typing is obviously wrong.

I once started with Assembly, Pascal, C and C++. So please don't start to explain to me what strict typing is and the benefits and so on, I know. JS uses dynamic typing by design. And I remember how awesome it felt when JS came out and we could write code without doing type juggling. And I believe that with type inference and some other tooling in the IDE we really don't need TS at all.


I’m noticing a pattern in your arguments.

You need to understand that I (and I suspect many others) don’t have the same experience as you. I don’t _fight/battle with_ the type system, I work with the type system - and I enjoy it. It saves me countless hours. I don’t actually use javascript without TypeScript anymore - it’s simply not worth _not_ using it - for me.

You ask whether it’s worth using it - and you keep telling people not to explain the primary benefits to you. The answer is yes for many people. It seems like you’re looking to be convinced that it’s worth it but you don’t want anyone to tell you what you already know. I’ve done this myself in the past - I’m not saying the situation is the same for you but it might be worth looking inside at: when I did this it was because I knew that x was worth it but I’d put myself in a position where getting down off my hill and accepting that x was worth it would require me to admit that I’d been wrong about it. Now I could double down on my position that x was simply not worth it, or I could come down slowly and start to enjoy the benefits of x more openly.

If you kinda feel that what I’ve just said might be a factor for you, then that’s already incredibly brave. If you’re interested in taking it further I can recommend role playing: for a week (just a week) role play as someone who thinks x _is_ worth it. Adopt the positions on the benefits that you already know. Act like you love it, act like the type checker REALLY helps you and saves your time, act like the types aren’t all that bad and CAN be used in usefully-constricting ways, and of course, help make your code even more self-documenting. You’ve gotta convincingly act, as if you’re going to win an Oscar. The audience fully believe you’re a true, light-seeing advocate for x.

Being able to change your mind is a great, noble and immensely valuable skill, and I can see that’s what you’re trying to do. Consider role playing as an advocate like I suggested above and perhaps you’ll have a new tool in your toolbox.


> a pattern in your arguments

> You ask whether it’s worth

> you keep telling people

I just want to point out that the account you're replying to isn't the OP.


It sounds you are essentially recommending therapy for those who don't like TS.


SM people enjoy their pain too ;-) Typescript for "Consumer" is great, but as soon as you must write own complex typings, that is everything, but really not a joy.


> I do TS for years now and still today I'm spending more time on fighting/pleasing TS compared to the actual code.

Admittedly, this mirrors my own experience, at least in some cases, which I shall not deny.

Was called in to help with this one particular TypeScript codebase that used React a while back, it was a mess. I suspect that some of the chosen abstractions were overengineered and overcomplicated (and perhaps underdocumented), but at the same time TypeScript made things more finicky and as a result the development velocity tended to be on the lower side of things, when compared to similar projects with JS. This was especially noticeable when new developers needed to be onboarded, though at the very least refactoring could be done with more confidence. Essentially they were not dealing with just sub-optimal code structure/architecture, not just the ever increasing complexity of React, but also how it all integrated with TypeScript on top of that.

It's a bit of a double edged sword, because when done right, TypeScript is objectively better than JS in at least some regards (refactoring for one, the type system obviously but also how well IDEs can figure out autocomplete because of it, or highlight issues that would otherwise manifest at runtime only with JS), however there is also potential for things to get much worse than your typical JS codebase, when done wrong.

This might be a silly comparison, but I'll compare it to something like PHP: when used correctly, you'll get something that lets you iterate pretty fast and just ship stuff, whereas if you go about it the wrong way you'll probably have a badly developed unreadable mess that's full of bugs or security issues, for a variety of reasons. In my experience, TypeScript codebases range from very good to very bad, whereas JS tends to be more mediocre in general, at least in regards to complexity and iteration speed. In regards to maintenance, TypeScript will win in most cases.

Use TypeScript responsibly and you'll have a decent time. Give it to someone who wants to be clever about things and you'll have lots of accidental complexity to deal with, more so than with the alternatives. Then again, personally I think that Angular did TS better than React or Vue, so this might be a niche view in of itself.


Sharing your experience is fine. Rebutting someone saying “this saves me time”, much less in a comment where they’re thanking someone for something they help make, is a bit ridiculous.


> I remember how awesome it felt when JS came out and we could write code without doing type juggling.

You enjoy working with dynamic typing. It more aligns with how you think and program. That's okay!

TypeScript may never be worth it, to you, and that's okay too! Not everyone likes and appreciates static typing.

If you ever do come to the datk side and think TypeScript is worth your time, it will be because that part is not a time waster but a time saver.


> Hmm, not my experience. I do TS for years now and still today I'm spending more time on fighting/pleasing TS compared to the actual code.

What are you doing exactly? I like TS, because it's one of the easiest to use type systems.

I'm also intrigued that you used C++ and think TS is bad, C++ error messages are legendary for being hard to understand.


What's Math.sqrt("hello")?


I use TS daily and I think this sort of argument doesn't give TS the credit it deserves.

Sure, you _could_ use it to check that you aren't making obvious errors like this (but this seems constrained to the "convince me that it's worth it" level of functionality, as it is just a nice-to-have for an existing working pattern).

Where TS shines for me is that it ENABLES new ways of "ad-hoc" coding where it's no longer risky to just create "convenience objects" to represent state when prototyping/refactoring, since you can avoid specifying concrete required types across a load of middle-man code and compose types at each level. This enables the pattern of splatting (composition over inheritance) a bunch of inputs to your data together, and then routing them to the points where they are needed. This scales nicely when you introduce monadic fun (processing some data with children, or something delay-loaded) since your type constraints basically write the boilerplate for you (I'm sure co-pilot will make this even more so in the far future).

There's also the fact that your can have your back-end APIs strongly typed on the front-end via something like GQL or Swagger, and this saves a TON of time for API discoverability.


Or 5/"potato"

In JS it's NaN, in TypeScript (or any other language with a remotely sane type system) it's a compilation error that saves you from running into a random NaN at runtime.


[flagged]


Please make your substantive points without breaking the site guidelines.

https://news.ycombinator.com/newsguidelines.html


What's Math.sqrt(value_from_a_package_that_was_definitely_a_number_before_you_updated_it)?


So then you have to make sure any inputs that get passed into Math.Sqrt aren't strings. You can pay the cost at runtime or compile time, and doing it at compile time saves you headaches later.


I agree that is not a good example, but the exact same thing can happen in more subtle ways that is hard to catch. For instance you might have a function that returns a user. Do you pass in the user ID argument as a string or a number?


>I agree that is not a good example

It's actually a great example, because in JS Math.sqrt("4") returns 2 because of JS's idiotic type coercion rules. So if you're passing in user input and don't typecheck it, it will work fine until someone inputs a letter instead of a number.


You won’t get far with attitude like that.


You know you can just use transpileOnly option and ignore some errors? I use it like that and it’s helpful to model data and speeds up development.


Assembly? No types there, just registers. The only distinction is floating point and non-floating point registers.


If you're just looking for general feedback, constructor typing has made my life really hard trying to type an existing JS library. In a JS object instance like `const user = new User()` you can call `this.constructor.staticMethod()` and it calls `staticMethod()` on `User` or up the inheritance chain. But TS doesn't type `.constructor` so you're out of luck. In the simple case you call `User.staticMethod()` but that doesn't work for an instance method on a superclass that wants to call the method of the constructor of the instance.

I understand why JS makes this difficult to type because you can mess around with the constructor. But for normal every day code you just expect `this.constructor` on an instance of `User` to be `User` and it really sucks that it isn't!


> you can call `this.constructor.staticMethod()` and it calls `staticMethod()` on `User` or up the inheritance chain.

This is where I have come to like typescript. 4 years ago, I would have agreed with you, but TS have moved me into a world where I wouldn't write that kind of code any more, and it honestly makes me sick to look at.

Instead I would just do `User.staticMethod` because this accomplishes several things:

  - super classes shouldn't know about inheriting classes. If they do, TS gives you interfaces and abstract classes for this purpose.
  - it still crawls up the proto chain, so the inheriting class doesn't need to know about every super class
  - no risk in `this` pointing to something unintentional (if someone calls or apply's your method)
  - shorter code, easier to read IMO, especially for less experienced devs


I might agree with you but sometimes we have to type up JS code that is written in different styles to what we'd personally prefer. TS should (a) let me generate the types that are used in JS. There are areas like proxies where that's just not possible, but in this case it feels like there's a disparity between TS and JS over classes. (b) I want to work with this code in my editor without red lines all over the place on perfectly valid code.

super classes don't need to 'know' about the inheriting classes for static inheritance to work. i.e. here is a simplified problem in the library I'm trying to add types to:

superclass:

  static hasField(name) { return false }
  constructor() {
    if(this.constructor.hasField('id')) { ... }
  }
subclass:

  static hasField(name) { if(name === 'id') return true; }
(it doesn't really look like that but you get the idea). That just works in JS, but in TS you get `Property 'hasField' does not exist on type 'Function'`. In the TS definition there are a couple of ways I can trick it to return the right thing for `this.constructor` but if I'm looking at a JS file in vscode with TS' checkJs flag on then this pattern should just work in my opinion.

edit: And I don't think I should have to trick it, that makes the definition harder to read and essentially wrong somehow.


Great of you to hop in. Just want to say that while I can typically navigate error messages in TS, I do occasionally have to do some googling on some error messages (specifically ones around generics that have a super type that apparently doesn’t necessarily agree with a subtype or something — still don’t quite get it), and it’s nice to see that the TS team recognizes the obtuseness of these messages is an issue.


TS#### error messages was a brilliant idea to make them more ~googleable~ bingable at least.


Isn't that pretty standard for compiler error messages? The C# compiler uses CS\d{4} for example. MSVC, MSBuild, various other build tools (at least on the Microsoft side) all use similar patterns with different prefixes.

That being said, it seems like Clang or GCC don't do that at all, which perplexes me a bit. Perhaps it doesn't matter much when error messages are never localized.


I guess TypeScript and C# having Anders Hejlsberg in common probably helps with things like that?


(A bit )off topic - chatGPT managed to infer your email address based on this comment. Required some hints though - most likely due to my lack of experience (first try). I was curious to see how it can improve indexing in general.


Thanks for responding, and thanks for your work for the community! I sometimes place myself in the shoes of devs building TypeScript, especially when I am a little frustrated, and most of the time I realize that a lot of these issues are incredibly hard to solve.

> i. Dependency management is indeed frustrating. TypeScript doesn't create a new major version for every more-advanced check. In cases where inference might improve or new analyses are added, we run the risk of affecting existing builds. My best advice on this front is to lock to a specific minor version of TS.

In my recent case, I needed to update Apollo Server to v4, which needs a newer version of TypeScript (see https://www.apollographql.com/docs/apollo-server/migration#t...), which in turn broke a type used from ProtobufJS. I am still navigating ProtobufJS source code to figure out what is the correct fix here.

> ii. My anecdotal experience is that library documentation could indeed be better; however, that's been the case with JavaScript libraries regardless of types.

Actually I think documentation is almost universally bad, I don't think Go or other languages are that much better (I don't want to wade into that debate though). The thing is, having TypeScript means you need more documentation. Even some pretty well documented JS/TS libraries completely neglect TypeScript and the end effect is that you end up having to guess things, or start reading source code. I don't actually know how you could improve this situation.

> iii. Our error messages need to get better - I'm in full agreement with you. Often a concrete repro is a good way to get us thinking. Our error reporting system can often take shortcuts to provide a good error message when we recognize a pattern.

I will look closer at this and start to think of how it could be better when I see a confusing message. I would probably count this as the biggest area that could yield improvement, because most of the time frustration is born of not being able to understand an error message. Often fixing things lead to trial and error. Can I just open an issue in the TypeScript repo for this sort of thing if I have a concrete suggestion?

> iv. Compilation can be a burden from tooling overhead. For the front-end, it is usually less of a pain since tools like esbuild and swc are making these so much faster and seamless (assuming you're bundling anyway - which is likely if you use npm). For a platform like Node.js, it is admittedly still a bit annoying. You can still use those tools, or you can even use TypeScript for type-checking `.js` files with JSDoc. Long-term, we've been investigating ways to bring type annotations to JavaScript itself and checked by TypeScript - but that might be years away.

Once it is part of the language, that will help a lot :) I considered using Deno or Bun to get me there on the server side, but need to be careful with production services.


Re libraries incompatible with certain typescript versions - e.g. protobufjs fix - it’s been my experience that you want to try and only use compilers specific to each library and compile libraries separately. It’s unfortunate but the JS community often tries to run all JS for a project through the same single compiler tool chain, using one global version of the compiler instead of relying on and effectively linking the JS output for each library. Unless you routinely rewrite third-party libraries to match your toolchain’s expectations, you’re going to have a hard time doing that.

For a library that generates code, that’s a special case, as the code it generates must target a particular language version. You have three choices: 1. Upstream a fix as you propose; 2. Side-by-side install both TS 4.6 and TS 4.7 using workspaces or sub-projects and have some of your code compile with 4.6 and then link the results or 3. Find a replacement that is updated to 4.7. For example, https://github.com/stephenh/ts-proto has 4.7 support listed in its readme.


We do generate the protobuf from a different repo which gets published on npm, and we could generate it for different versions of TS. I suppose all of this work is part of the overhead I am not so happy about using TypeScript.


This is a very interesting idea!


> Actually I think documentation is almost universally bad, I don't think Go or other languages are that much better (I don't want to wade into that debate though). The thing is, having TypeScript means you need more documentation. Even some pretty well documented JS/TS libraries completely neglect TypeScript and the end effect is that you end up having to guess things, or start reading source code. I don't actually know how you could improve this situation.

I think Rust approach is the best one so far, every package published in crates.io has an entry in docs.rs (that is created automatically when you publish your crate in crates.io), so I think Microsoft could improve it for every package published to create an entry in a domain specifically for js docs, if a project does not have it will look empty, but slowly the devs will start adopting it at the point that major libraries will improve the docs compared to what we have today.


> Can I just open an issue in the TypeScript repo for this sort of thing if I have a concrete suggestion?

Yes. There are even issue templates to guide you through writing an issue that the team will be able to address effectively.


>Once it is part of the language, that will help a lot :)

If you want to follow along, the proposal to allow type syntax to be part of JavaScript is here:

https://github.com/tc39/proposal-type-annotations

(To repeat Daniel, there is still a huge amount of work ahead)


> Can I just open an issue in the TypeScript repo for this sort of thing if I have a concrete suggestion?

aozgaa has already answered this one - but yes! If you have a concrete suggestion, that's fair game and we can brainstorm on the issue to think of something. We might not come up with something general enough to implement, but it's often a good seed to plant.

> which in turn broke a type used from ProtobufJS.

I am curious to hear what sort of issue you ran into. Was this the Apollo fork (https://github.com/apollographql/protobuf.js), or the original?


It's the original, which is being compiled on our internal protobuf definitions in a different repository and then installed post compile as an npm module.

I spent a while trying to grok the TS error but started to suspect that it didn't make a lot of sense, so I rm -rf node_modules, reinstalled, and it went away.

It would be hard to figure out what was at fault, but it's probably a combination of the node module system, protobuf, ProtobufJS and TypeScript. I do sometimes get funny type errors and restarting TypeScript makes them go away, in this case I had to go a step further.

I'll let you know if I get this again, or figure out what happened.




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

Search: