Since you've done typedef GenericCallback = void Function<T>(T)
you need to provide a generic method which matches the signature as a callback. The tricky part here is, you are doing that but not in the way you think.
In this line it looks like you're trying to specify the type for the closure you've created:
GenericCallback callback = <String>(String message) => printMessage(message);
However, Dart's rules for naming generic type parameters are strange in that you can use the names of existing types as the name of the type parameter. In other words, the following lines are all functionally identical and will provide a similar error:
GenericCallback callback = <String>(String message) => printMessage(message);
GenericCallback callback = <T>(T message) => printMessage(message);
GenericCallback callback = <int>(int message) => printMessage(message);
These generic closures are all completely valid and even built-in types like int
and String
will be treated as the names for type parameters in the scope of the closure.
In order to fix your error, you'll want to change the type parameter String
to have a different name that doesn't collide with a core type, and do one of the following:
- Update your invocation of
printMessage
to cast message
to a String
, although this will fail if T
isn't of type String
when the closure is called.
GenericCallback callback = <T>(T message) => printMessage(message as String);
- Update your typedef to expect a
String
parameter
typedef GenericCallback = void Function<T extends String>(T);
GenericCallback callback = <T extends String>(T message) => printMessage(message);
This is an easy mistake to make if you've come from a language which allows for template/generic specialization like C++. Keep in mind that, at least currently, you can't specialize a generic method or object and the generic type isn't assigned until the method is actually called or object is created.