After checking if a property of an object in Dart is of a particular subtype, Dart doesn’t seem to infer / know / remember that the property todo
is of that subtype further down in the code.
For example, if I check state.todo
is of type Todo_hasChildren
and then later use state.todo
as a Todo_hasChildren
type, I get a Dart analysis error ("The argument type ‘Todo3’ can’t be assigned to the parameter type ‘Todo3_hasChildren’")
I know how to fix this (convert using the as
keyword or assign the property to its own variable) but why does it not know the type? Is this temporary in the evolution of Dart or is this something that is permenant?
class MyState {
final Todo todo;
MyState(this.todo);
}
void doStuff(MyState state) {
if (state.todo is Todo_hasChildren) //
processHasChild(state.todo);
}
void processHasChild(Todo_hasChildren todo) {}
3
Answers
This is a known limitation in Dart’s type inference system. Dart’s type inference is based on the code’s control flow, and it can’t track the type of a variable across different branches of the control flow.
Here’s how you can do it:
or
Because
todo
is a property ofstate
, and Dart can only infer the type if you promote it from a local variable. This is a very similar case to the nullable type promotion. See also: Working with nullable fields.So you have to do this instead:
The reason is actually that subclasses of your
MyState
class may override the field with a getter that doesn’t consistently give the same value back. Like this:Now, when calling
doStuff
with aMyState2
the type check might pass the first time but when getting it for theprocessHasChild
it might return the wrong type.You can try out this full program to see for yourself that it occasionally crashes because of this: