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

Repurpose indexer for exact objects as computed keys #7862

Open
goodmind opened this issue Jun 28, 2019 · 10 comments

Comments

@goodmind
Copy link
Collaborator

@goodmind goodmind commented Jun 28, 2019

Proposal

Given that this code

type S = {|[key: string]: string|}

doesn't make sense with exact objects, why disallow indexers and not reuse this syntax for computed keys?

type SingleStringKey = {| [key: "a"]: string |} // {|a: string|}
type TwoStringKeys = {| [key: "a" | "b"]: string |} // {|a: string, b: string|}

type Hello<A, B, C> = {|
   ...{|[A]: string|},
   ...{|[B]: string|},
   ...{|[C]: string|}
|}

declare var test: Hello<"foo", "bar", "baz"> // {| foo: string, bar: string, baz: string |}

type SingleAnyStringKey = {| [key: string]: string |} // {|[key: string]: string|}

const hello: SingleAnyStringKey = {a: ''} // ok
const foo: SingleAnyStringKey = {b: ''} // ok
const baz: SingleAnyStringKey = {b: '', c: ''} // error

// singleton strings work like regular exact objects

Use case

This would enable computed keys (at least string literals) in types, also with spreads this would be very powerful feature

@goodmind goodmind added the discussion label Jun 28, 2019
@goodmind

This comment has been minimized.

Copy link
Collaborator Author

@goodmind goodmind commented Jun 28, 2019

@jbrown215

This comment has been minimized.

Copy link
Contributor

@jbrown215 jbrown215 commented Jul 1, 2019

We discussed doing something like this internally, but we wanted to mirror Typescript's syntax. They did a really good job with mapped types. Fortunately, most of the functionality in Mapped Types can already be encoded in Flow, but we don't have any equivalent of the in syntax they use to generate object types like you specify above from enums.

@goodmind

This comment has been minimized.

Copy link
Collaborator Author

@goodmind goodmind commented Jul 1, 2019

@jbrown215 maybe check this for alternative for in syntax #7849, or do you want it to be syntax?

@jbrown215

This comment has been minimized.

Copy link
Contributor

@jbrown215 jbrown215 commented Jul 1, 2019

If we're going to go with this kind of feature I'd like it to also clean up the syntax. The $ syntax used to denote experimental features, but it has sort taken on a life of its own. Our object type destructors are hard to call experimental at this point, so I'd like to see the syntax cleaned up at some point.

I think the amount of work in this project would be significant, too

@goodmind

This comment has been minimized.

Copy link
Collaborator Author

@goodmind goodmind commented Jul 1, 2019

I'm all for mirroring TypeScript syntax tho!

@jbrown215

This comment has been minimized.

Copy link
Contributor

@jbrown215 jbrown215 commented Jul 1, 2019

If this is something you are interested in taking on, then I can put together a project plan for what I had in mind to make sure we're on the same page. I'd also want to make sure we have the resources to support you here, since this project would probably be more than just a few PRs. I'd want to make sure you have dedicated reviewers and that the team is on board with the direction.

@jbrown215

This comment has been minimized.

Copy link
Contributor

@jbrown215 jbrown215 commented Jul 1, 2019

It's performance review season right now, so I won't be able to put all of this together until early next week.

@goodmind

This comment has been minimized.

Copy link
Collaborator Author

@goodmind goodmind commented Jul 1, 2019

Yeah, how would this syntax interact with spreads and another things? TypeScript disallows any properties in mapped types
Also it's strange that it accepts expression instead of type
image

@goodmind

This comment has been minimized.

Copy link
Collaborator Author

@goodmind goodmind commented Jul 2, 2019

Related #5276

@jbrown215

This comment has been minimized.

Copy link
Contributor

@jbrown215 jbrown215 commented Jul 9, 2019

I owe you a full answer here, but to explain how we could use them to interact with other things: we do this in the new type spread implementation by reading things as spreads. For example, type A = {...B, foo: number, ...C, bar: number} is basically type A = {...B, ...{| foo: number |}, ...C, ...{| bar: number |}}. We can do the same thing here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.