参数类型 'SomeType?' 无法分配给参数类型 'SomeType'

The argument type 'SomeType?' can't be assigned to the parameter type 'SomeType'

我在尝试调用函数时遇到错误:

The argument type 'SomeType?' can't be assigned to the parameter type 'SomeType'

我该如何解决这个问题?

该错误表明您正在尝试将具有可空类型 (SomeType?) 的变量作为参数传递给需要 non-nullable 的函数参数 (SomeType).

您必须先检查该变量是否不是 null 根据定义,可空类型的值可能为 null。将其传递给不期望 null 的函数显然是不好的。先检查。例如:

import 'dart:math';

final random = Random();

class Foo {}

/// Randomly returns a [Foo] instance or `null`.
Foo? maybeGetFoo() => random.nextBool() ? Foo() : null;

void printFoo(Foo fooInstance) => print(fooInstance);

void main() {
  Foo? foo = maybeGetFoo();

  printFoo(foo); // ERROR: The argument type 'Foo?' can't be assigned to the parameter type 'Foo'

  if (foo != null) {
    printFoo(foo); // OK, `foo` is now provably known to be of type `Foo`.
  }
}

通过检查localfoo变量是否为nullfoo可以自动type-promoted 到 non-nullable 类型。

对non-local变量(比如全局变量或成员变量)不起作用:

class Bar {
  Foo? foo;

  Bar(this.foo);

  void printMember() {
    if (foo != null) {
      printFoo(foo); // ERROR
    }
  }
}

要解决此问题,您要么必须使用中间局部变量(首选):

  void printMember() {
    // Shadow with a local variable to allow automatic type promotion to occur.
    final foo = this.foo;
    if (foo != null) {
      printFoo(foo); // OK, `foo` is now provably known to be of type `Foo`.
    }
  }

或者您必须明确地将转换为non-nullable类型:

  void printMember() {
    if (foo != null) {
      printFoo(foo!); // Compiles.
      printFoo(foo as Foo); // Compiles.
    }
  }

使用显式转换(无论是使用 ! 还是使用 as)通常应该是最后的手段。 重要的是只有在以下情况下才使用它您已经确定该值不是 null;如果它是 null,那么 !as 将在运行时抛出 TypeError 并使您的程序崩溃。此外,出于同样的原因,为什么 non-local 变量不会自动 type-promoted, 使用显式转换不一定安全 ,尽管在实践中通常应该没问题对于 non-pathological 代码。

另请注意,在某些不常见的情况下,甚至局部变量在检查后仍可能为空(例如,变量在检查后被重新分配)。参见 https://dart.dev/tools/non-promotion-reasons

我也强烈推荐阅读 Dart 的 Understanding null safety 文章。

最后,这并不是 null-safety 特有的;从 Foo?Foo 的转换只是 downcast 的一种形式,并且(除了后缀 ! 运算符),以上所有都适用总的来说是沮丧的。从基类型(例如从 Objectdynamic)到派生类型的自动类型提升也只会发生在局部变量上:

class Baz {
  Object maybeFoo;

  Baz(this.maybeFoo);
}

void main() {
  var baz = Baz(Foo());
  if (baz.maybeFoo is Foo) {
    printFoo(baz.maybeFoo); // ERROR

    printFoo(baz.maybeFoo as Foo); // Compiles.
  }

  final maybeFoo = baz.maybeFoo;
  if (maybeFoo is Foo) {
    printFoo(maybeFoo); // OK, `maybeFoo` is now provably known to be of type `Foo`.
  }
}