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
This would enable computed keys (at least string literals) in types, also with spreads this would be very powerful feature
/cc @jbrown215
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.
@jbrown215 maybe check this for alternative for in syntax #7849, or do you want it to be syntax?
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
I'm all for mirroring TypeScript syntax tho!
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.
It's performance review season right now, so I won't be able to put all of this together until early next week.
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

Related #5276
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.
Most helpful comment
I'm all for mirroring TypeScript syntax tho!