-
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
Empty object not of exact type with optional properties #2386
Comments
Yeah, looks like a bug to me. Thanks for the minimal example! |
For what it's worth, I am responsible for making this an error (in this commit). In general, unsealed things can't be exact, because other references to them can widen the type in unexpected ways. In this case, there are no other references, so it doesn't really make sense to consider the object literal to be unsealed. I think the fix here is to not create an unsealed object in this case. |
Still getting the error. Is that something that will be fixed? |
I would also like to see this fixed. Anytime you are using an options parameter it is helpful to allow {} |
@samwgoldman It's still an issue! |
Look at #4582 (comment) for a workaround |
@lgraziani2712 Why the thumbs down? Does it not work correctly? Please share your experience. |
The OP presents an object type with an optional attribute, while that workaround doesn't take in consideration those props. I tested myself with my object full of optionals attributes and it didn't work. |
Ok yep, it worked. I did it wrong: I kept the {||} exact pipes (Edit: when I tested before). Thank you @chrisblossom |
[ci skip]
type Breakdown = {| [string]: number |};
const breakdown: Breakdown = {}; =>
I think the explanation given in #2386 (comment) is the right one. But it's been a while... |
Here is a possible workaround until bug is not fixed: /* @flow */
declare type Criteria = {| option1?: number, option2?: string |};
declare export function init(criteria: Criteria): void;
const test = init({ ...undefined }); |
Another workaround is /* @flow */
declare type Criteria = $Shape<{option1: number, option2: string}>;
declare export function init(criteria: Criteria): void;
init({}); // ok
init({option1: 3}) // ok
init({option1: 3, rogueProp: 'secret'}) // errors as expected |
Another workaround, which to my mind is the cleanest of any I've seen here, is to just pass an explicit ({foo: undefined}: {|foo?: number, bar?: number|}); |
Recommend you add the label 'unsealed objects' to this and probably close #2977 as a duplicate of this so that progress/conversation can be tracked in one place. |
#7624 is also a duplicate |
Another workaround for this issue is to use ({ x: 3 }: {| x: number |}); // ok
({}: {||}); // error
(Object.freeze({}): {||}); // ok (workaround) I learned this from the thread at #2977; repeating it here in case it helps others, because this seems to be the canonical thread for this issue. If you weren't planning to mutate the object, then this workaround is quite clean because it should have no effect at all on the behavior of the code that consumes the object. And in situations where you are planning to mutate the object, I think you typically want the "unsealed object" behavior anyway so this isn't an issue in the first place. |
Minimal example:
https://flowtype.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgAKcAziQJYBGMWAogLY7ZgC8YAJLQB4CGAxhgA8Ab1RgwPAPwAuMADsArvUp4ATqgC+APnR84ckhjA5ZxMlRoMmWVmGEbUQA
Is this by design?
EDIT: inline an example
The text was updated successfully, but these errors were encountered: