为什么直接使用泛型值是不可能的,但如果从 Dart 中的方法返回也是可能的

Why direct usage of generic value is not possible but same is possible if returned from method in Dart

为什么在直接赋值时无法为通用字段赋值,但在使用变量引用或方法时却可以return值(这里,相同的值赋给变量和方法 return 值相同)?

class User {}

class Teacher extends User {}

class Student extends User {}

Future<User> getUser() {
  return Future.value(Student());
}

void main() {
  Future<Future<User>> fut = Future.value(getUser()); // <----- No error

  Future<Future<User>> fut2 = Future.value(Future.value(Student())); // <----- Getting error

  Future<User> userFut3 = Future.value(Student());
  Future<Future<User>> fut3 = Future.value(userFut3); // <----- No error
}

直接分配 Future.value(Future.value(Student())) 时出现以下错误。

Error: The argument type 'Student' can't be assigned to the parameter type 'FutureOr<Future<User>>?'.

因为在函数中你定义了 return 类型并且 dart 知道 return 类型,但是当直接赋值时 dart 不知道 Future.value(Student()) 有一个 Future<User> 类型].要解决此问题,您必须告诉飞镖值的类型,如下所示:Future.value((Future.value(Student())) as Future<User>); 这样 dart 就会知道这个值的类型并将其视为 Future<User>.

这里的问题是 Future<T>.value 的参数具有类型 FutureOr<T>。它可以是未来或价值。

此外,Dart 类型推断的工作原理是“下推”上下文类型,然后尝试使表达式在该类型上工作,最后将最终的静态类型向上推。 如果像 Future.value(...) 这样的表达式具有上下文类型,则始终从上下文类型推断缺少的类型参数。

写的时候

  Future<Future<User>> fut2 = Future.value(Future.value(Student()));

外部Future.value的上下文类型,我们知道它应该有的类型是Future<Future<User>>。这使得它的参数具有上下文类型 FutureOr<Future<User>>。 参数是 Future.value(Student()),我们对 Student() 还一无所知,因为我们还没有在类型推断中得到它,我们仍在朝着它努力。

一个Future<X>可以通过两种方式满足FutureOr<Future<User>>,要么是Future<User>,要么是Future<Future<User>>。 类型推断然后猜测是后者。这是错误的,但它还看不到。类型推断的工作方式,当有上下文类型时它必须使用上下文类型,但上下文类型不明确,最终选择了错误的选项。

您遇到了类型推断的边缘情况,其中可以通过两种不同的方式满足上下文类型,而向下类型推断选择了错误的方式。这是一个很好的启发式方法,如果你有一个 FutureOr<...> 上下文类型,并且你看到一个 Future 构造函数,你需要 FutureOr<...>Future 部分。当你有 FutureOr<Future<...>> 时它就会崩溃。所以,不要那样做!

总的来说,我的建议是 永远不要 在您的程序中包含 Future<Future<anything>>。它不仅避免了此类问题,而且还是您代码的更好模型。 一个最终完成到最终完成到某个值的东西的未来……只是让它最终直接完成到那个值。等待中间的未来只是无谓的忙碌