Reputation: 2781
I can't get polymorphic subtypes to work in arrays with Flow generics as I would in another language like Java.
Consider the following.
interface Person {
name:string;
}
class Employee implements Person {
name:string;
badge:string;
}
interface Workplace {
people:Array<Person>;
}
class MyOffice implements Workplace {
people:Array<Employee>; // ERROR: Incompatible with Workplace.people
}
This would fail in Java as well; but Java has a way to implement this correctly by indicating the people
array in Workplace
would contain subtypes of Person
.
interface Workplace {
people:Array<? extends Person>; // PSUEDO CODE: This is how Java supports subtypes
}
I have not been able to find a comparable mechanism in Flow. Flow discusses variance here: https://flow.org/en/docs/lang/variance/#toc-covariance and https://flow.org/en/docs/lang/depth-subtyping/
Which suggests that the following should work.
interface Workplace {
people:Array<+Person>;
}
But this syntax fails.
Is there a way in Flow to declare an Array covariant type?
Upvotes: 1
Views: 136
Reputation: 161677
Variance in Flow takes some getting used to. The core thing, as you've mentioned, is that these two operations would be invalid if
interface Workplace {
people:Array<Person>;
}
were allowed as-is:
var workplace: Workplace = new MyOffice();
// Not an `Employee`, can't allow adding to array
workplace.people.push(new SomeOtherPersonImpl());
// Not an `Employee`, can't allow replacing array.
workplace.people = [new SomeOtherPersonImpl()];
to get both of these properties, we need to
people
array read-only ($ReadOnlyArray).people
property read-only. (The +
you mentioned)Combining these, you end up with:
interface Workplace {
+people: $ReadOnlyArray<Person>;
}
Upvotes: 3