3 ms·
So, yes, arrays are treated correctly. But think about this: JavaScript has 6 or so fundamental types: undefined, null, number, string, boolean, symbol, object,
by ragnese 5y ago
So, yes, arrays are treated correctly. But think about this: JavaScript has 6 or so fundamental types: undefined, null, number, string, boolean, symbol, object, and array. All but two of those are primitive and therefore already immutable/readonly. So the readonly/Readonly<> feature is specifically for two of JavaScript's types. It only works on one of the two. That's 50%. We have a feature that only works for 50% of the cases it's supposed to.
It's unacceptable that TypeScript even allows us to write `readonly` on object types. It should be an array-only feature until it actually does what it says it does. Is it really unreasonable for me to expect them to not offer a feature that literally does nothing when I use it?
> And despite the above, I still don't think `readonly` is useless or harmful. I benefit from it and I'm glad it exists, even if it could be better.
I disagree and I think you're wrong. And here's why.
You just told me a few comments above that TypeScript has caught mistakes for you when you passed a readonly array (I'm assuming an array, because that's the only way it works) to a function that took a non-readonly array parameter. That sounds like a glass-half-full situation. Great! TypeScript helped you...
But. You just learned today, from some arrogant jerk on HackerNews, that readonly does NOT work on object types. So, if I assume that you've also used readonly on object types (because why wouldn't you? You thought it worked.), it means that there is a GOOD chance that you've made the very same mistakes with objects as you admitted to making with arrays. However, TypeScript did NOT catch those mistakes for you. Instead, you thought your code was correctly handling readonly and non-readonly objects.
So, did TypeScript do you a favor here or not? I sincerely believe that TypeScript did you a DISSERVICE. It tricked you. You probably relaxed the part of your brain that worried about that kind of thing when you wrote naked JavaScript. You relaxed it because you thought that TypeScript was actually helpful. And it DID catch some things, so why would you stress about it? I don't sit here and stress over whether I'm passing a number to a number field, because I know that TypeScript will tell me if I pass something that isn't a number. But what if it just didn't sometimes?
TypeScript would literally be better if it didn't allow readonly on object types. The code that you and I, both, wrote would likely be MORE correct if we knew that TypeScript wasn't going to help us. We'd both sit at our desks and say "Oh shit, I'm passing an object to this function. I better be very careful to see if the function is going to mess up if I mutate the object after passing it in." Instead, you and I got duped, and thought that readonly actually did stuff that it says it does. So we didn't pause and think carefully.
Fuck that. I'm becoming more and more convinced that everyone in this thread has Stockholm Syndrome. Everyone has just decided that TypeScript is awesome and I could point out 1,000 issues with its type system, and people are just going to say "well, don't use that" or "just pretend this type really means something other than what the compiler literally tells us". TypeScript could murder your cat and I'm pretty sure I'd get 10 replies saying "Well, I don't have a cat, so TypeScript is great!" or "Just don't have a cat. Duh."
- brundolf 5y agoI understand your reasoning. I think a case could be made that TypeScript shouldn't allow `readonly` as it's currently implemented on object types (though I also think the opposite case could be made). But here's the thing: at least in the real-world TypeScript code that I've written and seen over the years, `readonly` is usually not of crucial importance. It's a nice-to-have. I use it to remind myself "oh yeah, best not to mutate that in this section of the code". In most of those cases it's also obvious from context that we're working with the value immutably. Finally, I'm not usually mixing-and-matching mutable and immutable versions of the same type, which is where you're most likely to run into this problem. If a thing is readonly, it's probably readonly everywhere. I've had very few cases where it's "the world will blow up if this gets mutated in this one narrow situation which might accidentally happen because I passed an immutable value into a mutable argument". That's all very hand-wavy and anecdotal. I acknowledge that. But if you want to make good technical decisions you have to weigh the tradeoffs, not just the principles, and the reality of any usable type system layered on top of JavaScript is going to be messy and have compromises. I've used Flow - which tends to be stricter about these things (to a general disregard for JavaScript's idioms and syntaxes) - and it's frankly horrible. We migrated a huge codebase at one point from Flow to TypeScript because it was simply not helping us be productive. The other alternative is to use a language designed from the get-go to support a perfect type system - which can be a great option in some scenarios - but that comes with its own trade-offs if you're targeting the web ecosystem, especially if you have an existing codebase in JavaScript. You're going to have a hard time porting a huge existing codebase to Elm, for example. I personally believe that TypeScript is pretty darn close to a local optimum for "static type system that can be gradually applied to existing real-world JavaScript codebases". Your individual complaints are not technically wrong, but you're taking a hyper black-and-white stance that purposely focuses on details that aren't as significant and ignores real-world tradeoffs. If you don't like TypeScript, don't use it! The rest of us will continue to enjoy and benefit from it.