Repository navigation
add enforceReadonlyAssignability flag for smoother transition to true readonly modifiers #13002
Description
Activity
- addedDesign LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
on Dec 17, 2016 RyanCavanaugh commented
on Dec 17, 2016 MemberMore actionsThis was described at #6532 (comment)
Reacted by AlexAleksey-Bykov
readonlybasically means you may not modify it. It guarantees no actual immutability of the binding (heck, even Scala doesn't provide facilities that deep -val name = valueanddef name = valuecarry the same signature, andtoStringis a property). Consider it a case of "we're all consenting adults here", not "you shall not modify this value ever" (the latter is whatObject.freezeis for).Reacted by AlexReacted by Aluan Haddad and Anton TrofymenkozpdDG4gta8XKpMCd commented
on Dec 18, 2016 AuthorMore actions@iashmeadows next time you are buying a car and you read "a sport BMW coupe", you say sweet, just what I wanted, you write a check, get your car and drive it home, next day you are all excited to show it to your friends, you stop at a store to get a 6 pack on the way there, you open the trunk and put your beer in it, when you close it you BMW turns into Honda Odyssey... you are like what? you are all pissed and stuff, you take the beer out and it turns into BMW again, you are like what!!! you call the dealer who sold it to you, they drop on you first, it's normal, then they pick up and say you know it's accoring to issue #6532 where some housewife complained that the trunk of BMW isn't big enough for shopping at Costco and taking kids to the beach, and that's exactly why we made a hard decision to turn iT into Honda Odyssey every time anything is put in its trunk, you are like wtf!!! So you go there and you are like: nothing was said about this shit anywhere! And what you hear back is: well we never said we sell true BMW''s why are you surprised? And people around who saw it are like: hey let's be adults here. F**k what?
Reacted by Aluan Haddad, Bartosz Gościński, Maxim Kulikov, Maksim Sinik, Timur Seitosmanov, Marin Marinov and scottmohekeyReacted by Alex and AgamnentzarReacted by Daniel Rosenwasser, Claudia Meadows, normalser, Kagami Sascha Rosylight, Aluan Haddad, Tingan Ho, Yegor Roganov, Herrington Darkholme, Frederick Zhang, Eyal and 15 moreDanielRosenwasser commented
on Dec 18, 2016 MemberMore actionsRegardless of whether or not I agree on that perspective of
readonly, I have to admit I enjoyed the analogy. 😄Reacted by Claudia Meadows, Kagami Sascha Rosylight, Aluan Haddad, Anton Trofymenko, Asad Saeeduddin, David Goldstein, Maxim Kulikov, SlurpTheo and Ghabriel NunesAleksey-Bykov In case you missed it, the "we're all consenting adults here" was a reference to a common saying in the Python ecosystem, regarding member privacy, types, etc. 😉
(Basically, conventions are usually sufficient to imply "you're on your own" for diving into internals, and there's only so much you can do to prevent them from doing it, especially without the use of closures.)
aluanhaddad commented
on Dec 18, 2016 ContributorMore actions@isiahmeadows
In case you missed it, the "we're all consenting >adults here" was a reference to a common >saying in the Python ecosystem, regarding >member privacy, types, etc. 😉
Python gets a lot of things wrong. I never understood the appeal and popularity of that language. Irregardless that doesn't make it a good basis for anything.
It guarantees no actual immutability of the >binding (heck, even Scala doesn't provide >facilities that deep - val name = value and def >name = value carry the same signature, and >toString is a property).
I don't see the relevance,
valanddefboth mean the reference, to a property method or variable, may not be reassigned. They differ in eagerness vs laziness and some other characteristics, type inference characteristics for example, but they don't have different mutability. With respect to deep immutability, which is not what is asked for here, Scala does allow it, you just have to use the right modifier,valordef, all the way down and not var. Scala does enforce this at the type system level.Regardless, Scala has a nominal type system with support for optional explicit structural subtyping. Furthermore it doesn't permit these types of readonly violations. I don't think it is the right analogy.
I'm not saying TypeScript made a bad decision here, but personally I think it would have been great if
readonlyhad resulted in code emit usingdefineProperty({ writable: false, ... }), at least it would have made classes useful. But that's a whole other argument.Reacted by Tingan Ho, Eyal, Anton Trofymenko, Dmitry Starosta, Asad Saeeduddin and Junyoung/"Clare" JangType driven emit would be nice in many scenarios, but even if we never get that, a type error here would be useful. Do
readonlyproperties only get checked for reassignment within class members right now?Reacted by Daniel Earwicker and SlurpTheodanielearwicker commented
on Jan 8, 2017 More actionsRe: comments above, the issue here is not to do with emit, or the fact that readonly doesn't mean const. It's just the looseness of type checking between the interfaces with mismatched properties. If a property could be explicitly marked
mutable, it would not be satisfied by areadonlyproperty and the conversion disallowed.zpdDG4gta8XKpMCd commented
on Jan 9, 2017 AuthorMore actionshere is a dichotomy: a property is either readonly or writable, there is no other outcome
when we say
{ x: number }we mean writablex
when we say{ readonly x: number }we meanxis only for readingwhat else do we need? what is the third state implied by
mutablemReacted by Aluan Haddaddanielearwicker commented
on Jan 9, 2017 More actionsThat would be the ideal if the
readonlymodifier had existed forever. The problem is backward compatibility. To quote Anders Hejlsberg (@ahejlsberg) in the comment linked to above:Specifically, we can't interpret the absence of a readonly modifier to mean read-write, we can only say that we don't know. So, if an interface differs from another interface only in the readonly modifiers on its properties, we have to say that the two interfaces are compatible. Anything else would be a massive breaking change.
So now we have a trichotomy:
{ readonly x: number }-xis definitely not writable
{ mutable x: number }-xis definitely writable
{ x: number }-xmay or may not be writable - coder has not specifiedIf
mutablewas added to the language then your:interface WritableData { mutable value: number; }
would no longer be compatible with
ReadableData. It would allow us to specify definite mutability wherever we needed that safety.I think of this as similar to the bivariance compromise in TS today. Any fix to it in the future will allow us to improve the situation where we ask for it, but the default will have to continue to be bivariance, to avoid breaking so much existing user code.
(OTOH as TS 2.0 was a major version bump, maybe a massive breaking change would be acceptable to some, but TS is more cautious than that, which is a good thing IMO).
aluanhaddad commented
on Jan 9, 2017 ContributorMore actionsAleksey-Bykov Indeed a
mutablemodifier is effectively meaningless. Everything is mutable unless otherwise indicated.Daniel Earwicker (@danielearwicker) specifically for that reason there should not be new syntax because the old syntax will have to mean what the new syntax means implicitly and indefinitely. All this will do is create cognitive load
Specifically, we can't interpret the absence of a readonly modifier to mean read-write, we can only say that we don't know. So, if an interface differs from another interface only in the readonly modifiers on its properties, we have to say that the two interfaces are compatible. Anything else would be a massive breaking change.
It could be behind a flag : usually it's a convenient way to handle these kind of breaking changes.
Reacted by SlurpTheodanielearwicker commented
on Jan 9, 2017 More actionsbecause the old syntax will have to mean what the new syntax means implicitly and indefinitely.
But that isn't what the old syntax meant.
{ name: string; }didn't mean thatnamewas definitely mutable, and so it cannot be changed to mean that now. The world is full of TS 1.x code that uses such declarations for things that should not (or cannot) be modified because that code was written before TS 2. You can't change the meaning of all that code now.All widely used languages are products of evolution and contain some scars of that process. Only academic niche languages that no one uses are totally spotless.
Look at it this way: suppose functional programming takes over the world and everyone's properties are all now
readonly. Now it looks likereadonlyshould have been the default, to remove all the noise of everything being markedreadonly. But that change would break most existing apps utterly.danielearwicker commented
on Jan 9, 2017 More actionsArnaud Benhamdine (@abenhamdine) - yes though I expect there would be implications for maintaining type definition files so they can be used either way. If we have
readonlyandmutablethen all type definitions must explicitly say which their properties are, so they are not changed by the compiler switch.So even then, we'd still need
mutable.6 remaining items
zpdDG4gta8XKpMCd commented
on Jan 9, 2017 AuthorMore actions{ x: number } - x may or may not be writable - coder has not specified
you cracked me up :) so when you see
{ x: number }and you need to assignxit basically means the end of the work day for you because you can't make a decision based on how you defined itzpdDG4gta8XKpMCd commented
on Jan 9, 2017 AuthorMore actionsDaniel Earwicker (@danielearwicker) Asad Saeeduddin (@masaeedu)
let me share a secret:
- type definitions evolve naturally to keep up with latest features of TS
--noLiballows you to ignore new type definitions and use the old ones- in the old definitions there is no
readonly
problem solved
Reacted by Anton Trofymenkodanielearwicker commented
on Jan 9, 2017 More actionsCool, issue closed then!
aluanhaddad commented
on Jan 9, 2017 ContributorMore actionsRyan Cavanaugh (@RyanCavanaugh) I suppose not.
An off by default, option in the vein of
--enforceReadonlyAssignability, would be a very nice thing to have. It is of course a lot of time and effort, and I do not take that lightly, but it would be very beneficial. It seems as relevant, but of course less broadly valuable, as--strictNullChecksfrom a code correctness point of view.Reacted by Anton Trofymenko, Timm Preetz, Jared Russell, SlurpTheo, Junyoung/"Clare" Jang, Daniel M. and Leo FriedrichszpdDG4gta8XKpMCd commented
on Jan 9, 2017 AuthorMore actionsin support of the previous speaker, the topic was renamed
Reacted by Ryan Cavanaugh, Aluan Haddad, Daniel Earwicker, Arnaud Benhamdine, Anton Trofymenko, Marin Marinov and SlurpTheoReacted by Aluan Haddad and Anton Trofymenko- addedIn DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScriptDuplicateAn existing issue was already createdAn existing issue was already createdand removedDesign LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixedIn DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript
on Jan 9, 2017 RyanCavanaugh commented
on Jan 9, 2017 MemberMore actionsTracking this at #13347
Reacted by Aluan Haddad and SlurpTheoReacted by Aluan HaddadTo be honest I miss the old title. It was so much more memorable. These days, when I get frustrated with
readonlyand subsequently try to search for this issue, I actually have hard time finding it.Reacted by Anton Trofymenko, Timur Seitosmanov and Alexandre GalaysReacted by Aluan Haddad, Alexandre Galays and SlurpTheoReacted by Aluan Haddad and Alexandre Galays- locked and limited conversation to collaborators
on Jun 19, 2018
this can be seen in the nightly build as of Dec 17 (as well as at playground)this can't be serious, can it?why is it called readonly?please note there are no type assertions or any other attempts to trick the type system, it just simply doesn't work50+ errors left uncaughtUPDATE
constructive discussion starts here: #13002 (comment)