I have a class:
class Foo<T> {
final void Function(T) bar;
Foo(T t, {required this.bar});
}
and I'm passing int
value so that T
can be inferred as int
, but the issue is in the following code, t
is of type Object?
and not int
. Why is that so?
Foo(0, bar: (t) {
// `t` is of type `Object?`
});
Note: I'm not looking for a solution, which is to use Foo<int>(0, bar: ...)
. I want to know the reason why t
is not inferred correctly
CodePudding user response:
Your problem can be more clearly observed with:
class Foo<T> {
final void Function(T) bar;
Foo(T t, {required this.bar});
}
Type staticType<T>(T object) => T;
void main() {
var foo = Foo(0, bar: (x) => print(staticType(x)));
print(staticType(foo)); // Prints: Foo<int>
print(staticType(foo.bar)); // Prints: (int) => void
print(foo.bar.runtimeType); // Prints: (Object?) => void
foo.bar(42); // Prints: Object?
}
I'm not an expert on the inference rules (maybe lrn will provide a more authoritative and accurate explanation), but I believe that inference either can flow top-down (from function to arguments) or bottom-up (from arguments to function). Since you don't supply an explicit type parameter when constructing Foo
, Foo
's generic type argument T
must be inferred from its arguments. However, the argument type to the anonymous function also isn't specified, so it's assumed to be Object?
.
For Foo
's T
to be inferred as int
and for the anonymous function to be inferred to be (int) => void
would require inference to flow from the positional argument up to the function and back down to the named argument, which, to my understanding, Dart does not do, and you instead end up with the (Object?) => void
anonymous function being implicitly cast to (int) => void
.