メインコンテンツにスキップ

unsafe_variance

この型は安全ではありません: 型パラメータが非共変位置に出現しています。

説明

#

アナライザーは、インスタンスメンバーの結果型が、囲む宣言の型パラメータに対して反共変または不変である場合に、この診断を生成します。変数の結果型はその型であり、ゲッターまたはメソッドの結果型はその戻り値の型です。このリンターは、このようなメンバーについて警告します。なぜなら、呼び出しサイトで静的な警告やエラーなしに、実行時に型チェックが失敗する可能性が高いからです。

#

以下のコードは、Xf の型パラメータのパラメータ型として出現しているため、この診断を生成します。これはこの型パラメータの反共変な出現です。

dart
class C<X> {
  bool Function(X) f;
  C(this.f);
}

これは安全ではありません。c の静的型が C<num> で実行時型が C<int> の場合、c.f は例外をスローします。したがって、c.f の引数として a が正しい型を持つ場合でも、すべての呼び出し c.f(a) は例外をスローします。

一般的な修正

#

リンターによってチェックされるメンバーがプライベートであるか、またはプライベートにできる場合、this 以外のレシーバーでアクセスされないように強制できる場合があります。これにより、実行時型エラーが発生しないことを保証できます。たとえば

dart
class C<X> {
  // NB: Ensure manually that `_f` is only accessed on `this`.
  // ignore: unsafe_variance
  bool Function(X) _f;

  C(this._f);

  // We can write a forwarding method to allow clients to call `_f`.
  bool f(X x) => _f(x);
}

リンターによってチェックされるメンバーに対して、より一般的な型を使用することで、安全でない分散を排除できます。この場合、実行時型をチェックし、呼び出しサイトでダウンキャストを実行する必要がある場合があります。

dart
class C<X> {
  bool Function(Never) f;
  C(this.f);
}

c の静的型が C<num> の場合、型をテストできます。たとえば、c.f is bool Function(num) です。その型を持つ場合、num 型の引数で安全に呼び出すことができます。

また、Function のようなはるかに一般的な型を使用することで、安全でない分散を排除できます。これは、実質的に関数の dynamic 型です。

dart
class C<X> {
  Function f;
  C(this.f);
}

これにより、c.f(a) は動的に安全になります。引数 a が関数に必要な型を持たない場合にのみ例外がスローされます。これは元のバージョンよりも優れています。なぜなら、静的な型の不一致が原因で例外がスローされることはありません。整合性の理由で例外がスローされなければならない場合にのみスローされます。