使用“is”检查 Dart 泛型的运行时类型

Cra*_*rds 9 generics dart

我对 Dart 比较陌生,并且正在尝试对代数数据类型进行建模(例如 Swift 的具有关联值的枚举)。

但是,当我尝试检查值的运行时类型时,我看到了一些我不太了解的行为。考虑以下代码:

abstract class Fetchable<T> {
  factory Fetchable.success(T object) = FetchableSuccess;
  factory Fetchable.error(Error error) = FetchableError;
}
class FetchableSuccess<T> implements Fetchable<T> {
  final T object;
  const FetchableSuccess(this.object);
}
class FetchableError<T> implements Fetchable<T> {
  final Error error;
  const FetchableError(this.error);
}

void main() {
  // ------------- CASE 1 -------------
  final s = Fetchable.success("hi there");
  print(s.runtimeType);                             // FetchableSuccess<dynamic>
  print(s is FetchableSuccess);                     // true
  print(s is FetchableSuccess<String>);             // false
  print(s is FetchableSuccess<dynamic>);            // true

  if (s is FetchableSuccess) {
    print(s.object);                                // compile error 
  }
  if (s is FetchableSuccess<dynamic>) {
    print(s.object);                                // compile error
  }

  // ------------- CASE 2 -------------
  final e = Fetchable.error(StateError("uh oh"));
  print(e is FetchableError);                       // true
  if (e is FetchableError) {
    print(e.error);                                 // Works OK
  }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我创建了两个案例……我似乎无法objectsuccess案例中提取变量。该is关键字告诉我,这是一个FetchableSuccess<dynamic>(这似乎很奇怪......我以为飞镖不会删除类型?我本来期望它是一个FetchableSuccess<String>

尽管如此,如果我转换FetchableSuccess<dynamic>为编译器仍然告诉我它不知道子类中的object变量FetchableSuccess

相比之下,to FetchableError(它没有显式使用 type 的值T)...is工作正常并且编译器能够访问该error变量。

我错过了什么?任何指导将不胜感激。

Eri*_*nst 4

我们这里有几个问题:首先,您需要添加<T>到两个工厂构造函数的右侧。

如果你这样做, 的运行时类型s将是ReflectableSucces<String>它应该的样子,并且你将从true中的以下 3 行得到main

然后您正在测试s is FetchableSuccesswhichmeans s is FetchableSuccess<dynamic>,并且这不是静态已知类型的子类型Fetchable<String>,因此您不会得到提升(因此静态类型中没有object吸气剂,因此会出现错误)。显式测试s is FetchableSucces<dynamic>当然也受到同样的处理。

所以剩下的问题是,为什么那些缺失的 s 不会出现错误<T>?我现在正在寻找问题,这可能是一个已知的错误。

更新: https: //github.com/dart-lang/sdk/issues/34714解决了公共前端中没有进行推理的事实,尽管应该这样做。因此,我们使用来自分析器的推理进行分析,然后我们在运行时获得不使用推理的语义(因此默认为<dynamic>),这就是为什么我们会遇到这种不幸的冲突,其中实际类型参数是错误的运行时,并且没有编译时错误。当上述问题落地时应该得到解决。