I'm learning Flow and therefore I'm working on a little hobby project with JavaScript and Flow. I have a class Foo
and a different class Bar
that I want to take in an array of Foo
objects as an option in the constructor. However, I also want to be able to send some other data for each such object, and so I want to have an array where each element is either a plain Foo
object, or a Foo
object wrapped in an array or object.
However, when I tried to write the code for this, I got some weird errors that I don't understand the reason for. As far as I can tell, it thinks that there's a type conflict because Foo
isn't compatible with all of the types of the union, but as far as I understand it should only have to be compatible with at least one of them...
Here's the minimal code I needed to reproduce the exact errors I got (link to Try Flow example):
// @flow
class Foo { }
interface BarOptions {
foos: ( Foo | [ Foo ] | { foo: Foo } )[]; // line 6
}
class Bar {
constructor(options?: BarOptions) { }
}
const foo: Foo = new Foo();
const bar = new Bar({
foos: [ foo ], // line 16
});
I get the following errors:
Line 6:
tuple type: This type is incompatible with Foo
object type: This type is incompatible with Foo
Line 16:
tuple type: This type is incompatible with Foo
object type: This type is incompatible with Foo
Is there a intuitive (or unintuitive) reason for these errors?
Do you think it might be related to this open Github ticket? If we replace interface
with type
, it validates:
// @flow
class Foo { }
type BarOptions ={
foos:
Class<Foo> |
Foo |
Foo[] |
{ foo: Foo }
}
class Bar {
constructor(options?: BarOptions) { }
}
const foo: Foo = new Foo();
const bar = new Bar({
foos: Foo,
// foos: foo,
// foos: [foo],
// foos: { foo: foo },
});
I think BarOptions
should actually be a type alias instead of an interface. An interface declares a type that classes can implement. Interfaces are not data types and they should not have fields (containing data).
Here everything works if we just change interface BarOptions
to type BarOptions =
.
Alternatively you can change foo
to become a getter function:
interface BarOptions {
foos(): ( Foo | [ Foo ] | { foo: Foo } )[];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With