Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how can i strip readonly via mapped types? #13000

Closed
zpdDG4gta8XKpMCd opened this issue Dec 17, 2016 · 11 comments
Closed

how can i strip readonly via mapped types? #13000

zpdDG4gta8XKpMCd opened this issue Dec 17, 2016 · 11 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Dec 17, 2016

nightly build of Dec 17

given

interface Point {
   readonly x: number;
   readonly y: number;
}

i need a writable version of it

type WritablePoint = Writable<Point>;

where Writable is

type Writable<T> = {
    // what goes here?
}
@raveclassic
Copy link

I'm running into exactly the same issue.
For example, internal types of some complex tree structure should be immutable in public interface but for the sake of performance there should be a way for direct mutation in internal methods. It's a perfect place for a cast to a Writable<T> or even better Mutable<T>.

@zpdDG4gta8XKpMCd
Copy link
Author

Forget about it, readonly properties are useless due to #13002. Focus on something more rewarding.

@gcnew
Copy link
Contributor

gcnew commented Dec 18, 2016

I don't know whether this will be of any use to you but:

interface Point {
   readonly x: number;
   readonly y: number;
}

declare const p: Point;
declare function stripReadonly<T>(x: Readonly<T>): T;
stripReadonly(p) // { x: number, y: number }

See also: #12589

Edit: removing the readonly modifier should be done (I guess) via #4183 ;). Thus currently I'd go the other way around - declare a base type and make its fields readonly via Readonly<X>.

@zpdDG4gta8XKpMCd
Copy link
Author

It would have been a good choice it we chose mutable version by default, so that only in few places had we use Readonly <Point>, but the thing with immutability is that it is contagious and has to be a default choice across most of your entities. It spreads from the top level entities all the way down to lower level entities, because say you can't have a readonly Circle with a mutable centre point.

So if I go this route I would have Readonly<...> everyehere. Which is a questionable return for investment.

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Dec 19, 2016
@RReverser
Copy link
Contributor

So if I go this route I would have Readonly<...> everyehere. Which is a questionable return for investment.

@Aleksey-Bykov Not necessarily. Why can't you define them as following instead?

interface WritablePoint {
  x: number;
  y: number;
}

type Point = Readonly<WritablePoint>;

and then use Point as before without changing references in most places of your code?

@zpdDG4gta8XKpMCd
Copy link
Author

@RReverser read my answer above, tldr: when readonly is a default choice, so it should be encoded with a shorter signature

@RReverser
Copy link
Contributor

@Aleksey-Bykov Well, you define type just once anyway and in all the other places you can still use it with short name.

@zpdDG4gta8XKpMCd
Copy link
Author

@RReverser you are right, should have read you more closely, yes i guess it might be an option, need to sleep over it

@zpdDG4gta8XKpMCd
Copy link
Author

zpdDG4gta8XKpMCd commented Dec 20, 2016

@RReverser i tried it, major problem is that type declarations cannot be inherited like interfaces

type Point = Readonly<WritablePoint>
type Size = Readonly<WritableSize>
interface Box extends Point, Size { // <-- type error
}

the other way around is also possible but it looks awkward

interface WritableBox extends WritablePoint, WritableSize {
}
type Box = Readonly<WritableBox>

@basarat
Copy link
Contributor

basarat commented Dec 20, 2016

interface Box extends Point, Size { // <-- type error

Think type & / intersection solve it 🌹

@RReverser
Copy link
Contributor

Agree with @basarat, basically for inheriting type you'll need type Box = Point & Size; which looks less awkward IMO.

@mhegazy mhegazy closed this as completed Apr 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants