-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
enum indexer property not inferred properly #7128
Comments
This seems like a special case of indexers being totally broken on exact The simplest repro is ({a: 1}: {|[string]: number|}); // fails! :-( @jbrown215: When objects become exact-by-default, this will be a |
@wchargin: I've brought this up internally. We have no current plans for this, but I'll look into it more before we make the change to exact by default. |
Great; thanks. |
Looks like these lines are the culprit: https://github.com/facebook/flow/blob/master/src/typing/flow_js.ml#L6748-L6763 When taking that off, most of the stuff works fine and this specific problem is fixed, although some tests starts to fail. |
@jbrown215 made a PR to fix this: #7271 Looks like it does not fix the second case in this: try flow but that's most likely some other issue related to spreading with indexers. In overall I think that singleton string indexer properties should be treated as a regular keys from the get go but that's probably bigger change. |
@villesau: I'm curious to know what purpose an "exact object with an indexer" serves. At first glance, an indexer in an exact object looks like it makes the object equivalent to an inexact object with the same properties/indexer. Perhaps we should disallow indexers with exact objects altogether? |
First of all, consistency. You should be able to type everything as exact, otherwise it's not intuitive. Secondly, I think that See this example:
where exact types are spread. I want to keep them as exact. The key And lastly, like said, it would be at least prework to get this example working. When moving away from inexact types, we need to spread exact types with indexer properties, I opened it up a bit also in other issue that I did, which I ironically didn't notice to be the same issue that I already reported earlier: #7240 |
I think we view exact objects a little differently. Take this example:
IMO, the exact object should fully capture the properties in the object. An indexer by nature is "imprecise" and feels weird when combined with a precise representation of an object.
I think this friction is necessary to let people know that what they think is exact doesn't actually behave like an exact object should (as far I as view exact objects, which is a place where we disagree).
I get why this seems weird from that perspective, but consider it from the other perspective. Why should you be allowed to specify an imprecise specification for an exact object?
I think the solution there might be to keep the objects inexact and fix spreads. I'm not even sure what the correct behavior for an exact object with an indexer being spread should be. Couldn't it overwrite all of the object's props if the object with the indexer was spread after other props were specified? |
Thanks for the profound arguments! Note that indexer might have well defined string literal as indexer: This is necessary when building libdefs. That's the main issue here, and those are essentially the ones we need to spread too.
To me the main issue in this example is that indexer properties should always be optional types: #6980
I think it as precise: It precisely defines that the key can be anything, but values of any key is well defined. look at this inexact example: as you see it has property but it's not. So I'd argue that inexact indexer objects are broken here and they actually behave pretty much exactly how exact indexer objects should behave. That said, the strength of inexact indexer object should be very close to plain
If the key is string literal, it should work like normal exact object. Otherwise I'd expect something like:
where precisely defined keys would overrule indexers. I didn't validate that this would be the best behaviour, but this is what I'd expect at first glance and what would be the least surprising to me. Anyhow, there are three different cases here: Indexer object with arbitrary key ( |
I think both of our interpretations are reasonable, but we disagree in our starting points. I'll talk to Sam, who has plans for our object types, to see what a good mental model for exact vs. inexact is going forward |
Here is very related issue: #3162 |
As of Flow 0.111.0, Flow is specifically asking us to make indexed
I don’t understand the team’s position on this—if exact objects with |
This is a bug in the error message. It recommends making the object type exact because it is inexact, not because it has an indexer. We should only recommend making the object exact if there is no indexer. Will fix! |
I think a string union indexer is the case to focus on, because it comes up in enums, and type Unit = 'ft' | 'm'
const attributes: {[Unit]: {toMeters: number, displayText: string}} = {
ft: {inMeters: 0.3048, displayText: 'Feet'},
m: {inMeters: 1, displayText: 'Meters'},
} And @villesau the corresponding TS type is actually type UnitAttributes = Record<'ft' | 'm', {toMeters: number, displayText: string}> |
try flow
This prevents writing certain libdefs, e.g this: try flow
This has never worked. It's especially important when moving exact by default types since
A & B
would not work in that kind of cases anymore. Now the example is possible to make working with limitation that exact properties are not supported, and usingA & B
approach.Would be very interesting to try to fix this by my self, but Flow codebase is a bit frightening. Any pointers what lines should I look at and would this be big task to fix?
The text was updated successfully, but these errors were encountered: