空安全模式下如何避免空断言?Dart代码合规问题
解决Dart非空断言与类型兼容问题
问题背景
我正在学习Dart语言,使用dart_code_metrics工具确保代码符合规范,当前启用了avoid-non-null-assertion规则。
注:以下代码用于复现大型代码库中从JSON文件读取unitString时遇到的问题,程序无法控制JSON中的内容。
pubspec.yaml配置
environment: sdk: '>=2.15.0 <3.0.0'
原问题代码示例
// ignore_for_file: avoid_print import 'package:qty/qty.dart'; void main() { const String unitString = 'in'; // 若unitString不是长度单位,Length().unitWith会返回null if (Length().unitWith(symbol: unitString) == null) { print('units $unitString not supported.'); } else { // 下面一行因使用!触发avoid-non-null-assertion规则 final Unit<Length> units = Length().unitWith(symbol: unitString)!; final qty = Quantity(amount: 0.0, unit: units); print('Qty = $qty'); } }
遇到的错误
- 使用
!会触发dart_code_metrics的avoid-non-null-assertion规则 - 去掉
!会出现类型错误:
A value of type 'Unit
?' can't be assigned to a variable of type 'Unit '.
Try changing the type of the variable, or casting the right-hand type to 'Unit'.
- 尝试强制转换为
Unit<Length>后,实例化Quantity时仍会因构造函数要求非空的Unit<Length>而报错
解决方案
核心思路是提前存储可空方法的返回值,利用Dart的类型提升特性消除非空断言,修改后的代码如下:
// ignore_for_file: avoid_print import 'package:qty/qty.dart'; void main() { const String unitString = 'in'; // 一次性获取方法结果并存储,让Dart能追踪类型状态 final Unit<Length>? maybeUnit = Length().unitWith(symbol: unitString); if (maybeUnit == null) { print('units $unitString not supported.'); } else { // 此时Dart自动识别maybeUnit为非空类型,无需断言或转换 final qty = Quantity(amount: 0.0, unit: maybeUnit); print('Qty = $qty'); } }
原理说明
- 将
Length().unitWith的结果存储到可空变量maybeUnit中,避免重复调用方法,同时让Dart的类型系统能跟踪变量的空值状态 - 在空值判断的
else分支中,Dart会自动将maybeUnit的类型从Unit<Length>?提升为Unit<Length>,无需手动添加非空断言或强制转换 - 既满足dart_code_metrics对避免非空断言的规范要求,又彻底解决了类型不兼容的问题
内容的提问来源于stack exchange,提问作者YetAnother BugHunter
相关产品推荐
相关产品推荐

