-
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
Document object type spread #3534
Comments
It seems to be more like ({b: 0 }: B); // works
({b: '' }: B); // also works |
This seems to be the intended behaviour indeed. Basically, spread type is a type of result of object spread operation. Object spread only copies own properties, but object properties can also be inherited. Another thing to remember is that non-exact objects can have any properties other than defined. So here are the rules: type A = {
a: number
}
type B = {
b: number,
...A
}
// The same as
type B = {
a?: number, // every property from spread becomes optional
b: mixed // every property before non-exact spread becomes mixed
}; type A = {
a: number
}
type B = {
...A,
b: number
}
// The same as
type B = {
a?: number,
b: number // properties after spread stay the same
}; type A = {
a: number
}
type B = {
b: number,
...$Exact<A>
}
// The same as
type B = {
a: number,
b: number
};
|
That's brilliant, thanks for this super useful addition to the language. I've been longing for this for quite some time. Shouldn't you write a blog post or something? This is really a killer feature. |
Sorry, last week got away from me and I didn't have docs prepared for the release of 0.42. Working on it, though. |
@vkurchatkin Let me see if I understood correctly. In your example…
…an object called |
@guigrpa yes, sounds right |
I have a follow up question that I think is related. I'm trying to use object type spread to increase the strictness of an object, but there's behavior that I don't understand. Here are my types: type Action = {
type: string,
payload?: any
}
type MyAction = {
payload: any,
...$Exact<Action>
} I'm hoping that by doing this, However, when I do this:
Why doesn't flow throw an error on |
@lewisf I agree, this looks like a bug |
EDIT: I just noticed the post right above about strictness ;). Heres perhaps another example that ultimately tries to use the lenient type (e.g. relay mutation) We start with lenient base types, then start restricting them in our components. I could go into more details, but it may be too much context, so I'll let the example speak for itself: type Lenient = {
a?: number,
c: string
}
type Restrictive = {
...$Exact<Lenient>,
a: number,
}
function foo(bar: Lenient): string {
return 'baz'
}
const r: Restrictive = { a: 1, c: 'foo' };
// Cast from Restrictive to Lenient fails
const l = (r: Lenient)
// Restrictive is incompatible with Lenient
foo(r)
I'm struggling to see why This is a big problem for us, what part of object type spread am I missing? |
Using |
@rosskevin I'm not sure if this is the Correct answer, but it works if you make the "lenient" field covariant, eg Note that |
It seems to work differently with exact types: // @flow
type A = {|
a: number,
aa: string
|}
type B = {|
b: boolean,
bb: Array<string>
|}
type AB = {| ...A, ...B |}
const ok: AB = {a: 1, aa: 'aaa', b: false, bb: ['ya', 'yaa']} // works
// uncomment for errors
// const extraField: AB = {a: 1, aa: 'aaa', b: false, bb: ['ya', 'yaa'], badField: 321}
// const missingField: AB = {a: 1, b: false, bb: ['ya', 'yaa']} |
@vkurchatkin I think your explanation would make sense if we were talking about JS objects. But in this case we are spreading types right? As seen in the original post all the props are well defined so IMO it's clear that the spreading should work like explained in the original comment. There is no risk that there would leak some magical types that overrides some properties. The behaviour where something becomes optional or mixed ruins the idea of spreading and is very confusing. Am I missing something here? Fixing by using exact does not sound like a solution to me. As far as I know, non-exact means that the object can contain some other values that the developer is not interested in (e.g they just flows trough the system without dev needing to know about them). But the types still can't contain anything else than what's defined so it should be very clear what has been spread and what has not been spread. |
Object type spread is documented as of 4865dee, also this blog post: https://medium.com/flow-type/spreads-common-errors-fixes-9701012e9d58 |
Given:
I'd expect B to be equivalent to:
But instead it's:
Why? Is that the intended behavior?
Tested in v0.42.0 and master: https://flowtype.org/try/#0C4TwDgpgBAglC8UDeAoKUCGAuKA7ArgLYBGEATgNwoC+VokUAQgsmlMTgSeVegHQCYVamxQBjAPa4AzsCgAPHHERJMOAIxRa4qbKggczFWqj5cAEwgAzAJa4I5gDTscZy7fvmtVIA
The text was updated successfully, but these errors were encountered: