参数类型 '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
变量是否为null
,foo
可以自动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 的一种形式,并且(除了后缀 !
运算符),以上所有都适用总的来说是沮丧的。从基类型(例如从 Object
或 dynamic
)到派生类型的自动类型提升也只会发生在局部变量上:
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`.
}
}
我在尝试调用函数时遇到错误:
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
变量是否为null
,foo
可以自动type-promoted 到 non-nullable 类型。
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 的一种形式,并且(除了后缀 !
运算符),以上所有都适用总的来说是沮丧的。从基类型(例如从 Object
或 dynamic
)到派生类型的自动类型提升也只会发生在局部变量上:
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`.
}
}