Home > other >  Why type inference is not able to infer a type in a function callback?
Why type inference is not able to infer a type in a function callback?

Time:12-28

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.

  •  Tags:  
  • dart
  • Related