type T = $Exact<{}>;
const t: T = {} // flow error
The only work around seems to be to replace $Exact<{}>
with { [any]: empty }
type E = { [any]: empty }
const e: E = {}
Or to simplify without an alias...
const foo: {| bar: 'bar' |} = { bar: 'bar' }
const fooError: {||} = {}
4: const fooError: {||} = {}
^ object literal. Inexact type is incompatible with exact type
4: const fooError: {||} = {}
^ exact type: object type
You're right, this is a surprising behavior.
+1
I encountered this when trying to assign an empty object to an exact type defined with an indexer.
type Exact = {|
[KeyType]: ValueType
|};
Seems like this can be resolved by defining the type as
type PossiblyEmptyExact = Exact | {};
That's not a better workaround since {}
is a superclass of _all_ structs. Consequently,
type Foo = {| bar: number |} | {};
const foo: Foo = {bar: "baz"};
is happily accepted by the compiler.
Using a non-exact type would be more type-safe.
@marcianx: Thanks. Seems like I was so happy it worked, I didn't think it through.
@hon2a https://github.com/facebook/flow/issues/5688 has two workarounds. I've used the $Shape
one successfully for my workaround.
type Foo = $Shape<{bar: number}>;
const foo1: Foo = {bar: "baz"}; // wrong field type
const foo2: Foo = {qux: "baz"}; // property missing
Guys, please beware of this issue with shapes: https://github.com/facebook/flow/issues/5884. The currently accept null
and undefined
.
@marcianx: $Shape
allows objects with some of the properties missing.
type T = $Shape<{ a: number, b: number }>;
const partial: T = { a: 1 }; // no errors
In my case $Shape
is of no use as I need this for maps (defined with an indexer, e.g. type T = {| [KeyType]: ValueType |}
).
@mhagmajer Thanks for pointing this out! The easy workaround for this is to ensure that this is an object via & {}
.
type Foo = $Shape<{bar: number}> & {};
const foo: Foo = null; // null is incompatible
@hon2a Thanks for mentioning. I should have explicitly mentioned this -- indeed, this workaround is only for the case where you wish all fields to be optional (which was my case when I ran into this bug).
I think this code does not work for the same reason.
type T = {|a?: number|};
const t: T = {};
Closing in favour of https://github.com/facebook/flow/issues/2977
Most helpful comment
Or to simplify without an alias...
You're right, this is a surprising behavior.