dart-nulsaftey和使用旧包

  • 本文关键字:dart-nulsaftey dart null
  • 更新时间 :
  • 英文 :


我已经启用了dart 2.8 nulsaftey实验。

我已经将我的应用程序转换为nulsaftey,但它使用了一个旧的nulsafety前包。

问题是旧包有一个可以返回null的方法:

/// Returns the environment variable with [name] or null if it doesn't
/// exist
String env(String name);

其用途如下:

var home = env('HOME');

如果HOME环境变量丢失,env将返回null。

问题是env被声明为返回String

所以当我写的时候

var home = env('HOME');
home ??= '/home';

我得到一个错误:

The operand can't be null, so the condition is always false.
Try removing the condition, an enclosing condition, or the whole conditional statement.

考虑到所有的nulsaftey发布公告都说你可以将nulsafte与旧的包一起使用,我猜有一些方法可以将导入的包声明为非nulsafe。

问题是我找不到任何关于如何做到这一点的文档。

空安全尚未发布!这就是为什么您需要提供实验标志

语言版本控制

默认情况下,库中是否支持null安全性取决于其语言版本。任何2.8或更低版本的语言都被视为选择退出零安全,2.9或更高版本(可能会更改(被选择加入。语言版本本身可以来自以下两个地方之一:

  1. 包声明的SDK约束的最小绑定。以下软件包的语言版本为2.8

name: foo
env:
sdk:
">=2.8.0 <3.0.0"
  1. 文件顶层的语言重写注释,位于任何其他声明之前。以下库的语言版本为2.8
// @dart=2.8
class Foo {}

语言重写注释将优先于SDK约束,但仅在声明它的单个库中。

空安全和非空安全代码之间的交互

但是,在没有不同的包或不正确的语言版本的情况下,您遇到的问题是可复制的,并且与空安全和非空安全代码之间的交互有关。考虑以下示例:

// @dart=2.8
String foo() {
return null;
}
// @dart=2.9
import 'a.dart';
void main() {
var value = foo();
value ??= 'asd';
}

foo的返回类型没有变成String?,而是被标记为String*——这被称为遗留类型在选择的库中,遗留类型被视为非null类型。遗留类型的目标是通过有序迁移更容易迁移到零安全考虑以下示例:

// @dart=2.9
void foo(String value) {
// do something with non-null String.
}
// @dart=2.8
import 'a.dart';
void main() {
foo(getStringFromAPI());
}

虽然foo需要一个非空字符串,但入口点不可能实际传递一个,因为它还没有选择加入。如果不将遗留类型视为不可为null的类型,就不可能逐步迁移,因为所有库都需要一次更新,或者只更新为接受可为null类型。

无序迁移

通过调用尚未从空安全库迁移到空安全的代码,您增加了在依赖关系最终迁移时被破坏的风险。在您的示例中,如果home被视为不可为null,那么更新到具有更新的返回值String?的依赖项版本将导致编译错误。

对于您的特定情况,我建议将home的类型特别注释为String?。这是一个完全有效的类型注释,因为通常TT*总是可分配给T?。它也更正确,因为您知道API可以返回null。

String? home = env('HOME');
home ??= '/home';

2021年6月版:

零安全已经释放,耶!默认启用空安全的Dart的第一个版本最终是2.12,而不是上面问题中所述的2.9

相关内容

  • 没有找到相关文章

最新更新