Array<A|B> should be compatible with Array<A>
aldendaniels opened this issue · comments
This:
declare function func(things: Array<string | number>): void;
declare var value: string[];
func(value);
Gives:
1: declare function func(things: Array<string | number>): void;
^ number. This type is incompatible with
2: declare var value: string[];
^ string
Perhaps related: #2507
Array
s are invariant: T
being a subtype of U
does not mean Array<T>
is a subtype of Array<U>
. Otherwise you could push a number
onto things
inside of func
and there would be a number
in value
, which has type Array<string>
.
Can't because func(value)
could add a number
to value
.
function func(things: Array<string | number>): void {
things.push(1);
}
var value: string[] = ['f'];
func(value);
console.log(typeof value[1]); // a number!
@jesseschalken @omerzach Wow, thanks for the quick follow up! Is there a way to make flow allow this if the function doesn't mutate the array - e.g. using a readonly array?
You can use func<T:string|number>(things: Array<T>): void
or, of any Iterable
will do, func(things: Iterable<string|number>): void
(Iterable<T>
is covariant in T
).
See also #2333
@jesseschalken Sure enough! func(things: $ReadOnlyArray<T>
) also appears to work
Closing in favor of #2333