From the doc:
The mixed type is a supertype of all types.
So:
const foo: Object = {};
const bar: mixed = foo;
No errors!
OK, since mixed is the Supertype of 'Object'.
But:
const foo: Array<Object> = [{}, {}];
const bar: Array<mixed> = foo;
144: const bar: Array<mixed> = foo;
^^^^^ mixed. This type is incompatible with
143: const foo: Array<Object> = [{}, {}];
^^^^^^ object type
WTF ??? Now mixed is not the supertype of Object ???
This is expected behavior. Your assertion that Array<B> should be a subtype of Array<A> if B is a subtype of A isn't true (Ed: corrected, per comment below). Phrased differently, your issue asserts that arrays are covariant. In fact, arrays are invariant.
Read-only arrays _would_ be covariant, but since arrays are mutable in JS, they are invariant in Flow, which prevents unsound code like the following:
class A {}
class B extends A {}
var bs: Array<B> = [];
var as: Array<A> = bs;
as.push(new A); // this would be bad!
OK thanks for the explanation, it make sense now.
But I never said this:
Your assertion that
Array<B>should be a subtype ofArray<A>if A is a subtype of B isn't true."
Instead:
Your assertion that
Array<B>should be a subtype ofArray<A>if A is a supertype of B isn't true."
You're right鈥擨 misspoke. Thanks for the correction!
No prob.
You welcome :)
@samwgoldman thanks for the explanation! it seems to be the general rule for all the languages that only read-only types can be covariant
Hum...
OK, following your explanation:
class Foo{}
class Bar extends Foo{}
const a: Array<Bar> = [];
const f: Array<Foo> = a;
164: const f: Array<Foo> = b;
^^^ Foo. This type is incompatible with
163: const b: Array<Bar> = [];
^^^ Bar
Alright ! Bar inherits from Foo, arrays are invariant, error is legitimate.
But:
const s: Array<String> = [];
const o: Array<Object> = s;
o.push({ a: 'dat fail :)' });// Holy hell !!!
No errors!
String inherits from Object but everything is OK ???
This is an inconsistent behavior with built-in Type ?
Nice observation! The Object type is a supertype and subtype of all objects, similar to any. So Array<Object> is compatible with Array<String>, since Object <: String _and_ Object :> String.
Aside, I wish we had named Object something like AnyObject instead, and made Object more specifically the type of new Object with methods like toString but nothing else.
Wow Indeed I could not even supposed Object acts as any (a kind of wildcard/bypass).
IMHO it's a bad behavior which mislead. I do not permit to emit a criticism you have made a great job with Flow, but please at least put the information in your website doc:
Object: The Object type is a supertype and subtype of all objects. That means Object is not the strict equivalent of the native/built-in Object type but is more similar to any.
To sum up: any is the sub/supertype of all scalars and objects whilst Object is the sub/supertype of all objects only (except for the Array type).
Array: IMPORTANT: Arrays are generics invariant.
Thanks for your support @samwgoldman.
Most helpful comment
Wow Indeed I could not even supposed
Objectacts asany(a kind of wildcard/bypass).IMHO it's a bad behavior which mislead. I do not permit to emit a criticism you have made a great job with Flow, but please at least put the information in your website doc:
Object: The Object type is a supertype and subtype of all objects. That means Object is not the strict equivalent of the native/built-in Object type but is more similar to
any.To sum up:
anyis the sub/supertype of all scalars and objects whilstObjectis the sub/supertype of all objects only (except for the Array type).Array: IMPORTANT: Arrays are generics invariant.
Thanks for your support @samwgoldman.