我正在尝试定义一个需要接受泛型参数并返回相同类型值的回调函数。请记住,以下示例是我实际需要的简化版本。
final T Function<T>(T value) self = (value) => value
这导致以下错误,我似乎无法摆脱。
The argument type '(dynamic) → dynamic' can't be assigned to the parameter type '<T>(T) → T'
dart(argument_type_not_assignable)
唯一似乎有效的方法是给值一个类型,但这首先违背了使用类型参数的目的。
final T Function<T>(T value) same = <String>(value) => value;
我需要它是通用的,以便调用者可以传递它期望的类型作为返回。我还需要将它存储在一个变量中,以便我可以将它作为回调函数传递。
如果这不是直接可能的,您知道任何解决方法吗?先感谢您。
如果要求不明确,这里有一个更完整的示例。
abstract class Provider<T> {
T get bar;
}
class StringProvider extends Provider<String> {
String get bar => 'bar';
}
class NumberProvider extends Provider<int> {
int get bar => 42;
}
class Foo {
final T Function<T>(Provider<T> provider) provide;
const Foo({ this.provide });
}
test() {
final foo = Foo(provide: (provider) => provider.bar);
String strValue = foo.provide(StringProvider()); // should be 'bar'
int numValue = foo.provide(NumberProvider()); // should be 42
}
令人讨厌的是,Dart 实际上理解
foo.provide(StringProvider())
将返回一个字符串,使用 NumberProvider
确实会返回一个整数,但是,对于实际给变量赋值的那一行,错误仍然会增加。final foo = Foo(provide: (provider) => provider.bar);
The argument type '(dynamic) → dynamic' can't be assigned to the parameter type '<T>(Provider<T>) → T'
最佳答案
事实证明,我可以通过在定义值时给出任何具体类型来欺骗类型检查器。请注意 dynamic
不允许,但其他任何事情都可以。
final foo = Foo(provide: <int>(provider) => provider.bar);
这既消除了错误,又允许
provide
方法在调用时返回正确的类型。总而言之,这似乎是类型检查器的一个简单缺点,而不是使用已经存在的语言功能实际上不可能或难以实现的。我将在该语言的 GitHub 存储库上提出一个问题,以便进一步调查和讨论。
更新 #1 : 该问题已在 GitHub 上打开.
更新 #2 :问题已解决,事实证明该行为是设计使然。报价Erik Ernst来自 SDK 团队:
Try this:
final foo = Foo(provide: <T>(Provider<T> provider) => provider.bar);
!The problem is that you're passing a non-generic function to the Foo constructor, and you should pass a generic function. There is no subtype relationship between a generic function type and a non-generic function type, so according to the type checker you might as well pass a String, and that's the reason for the 'can't be assigned to' message.
事实证明,只需添加
<T>
在参数列表(而不是原始解决方法中的 int
)解决问题之前。final foo = Foo(provide: <T>(provider) => provider.bar);
这迫使 Dart 理解 provider 的类型是
Provider<T>
并且该方法将返回类型为 T
的值,使我们免于使用具体类型并仍然摆脱错误。
关于generics - Dart 中带有泛型类型参数的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55848042/