关于 dart-use-pattern-matching
这是一项指导 Dart 3+ 模式匹配的技能,面向 Dart 开发者,涵盖数据校验、解构及穷尽分支处理。
主要功能
- 01Map 和 List 模式匹配与解构
- 02Record 模式解构
- 03sealed 类的穷尽匹配
- 04关系与逻辑模式及条件守卫
- 05switch 表达式与语句的选择
适用场景
- 01校验并提取嵌套 JSON 字段
- 02解构函数返回的 Record
- 03为 sealed 类状态编写穷尽分支
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dhruvanbhalara/ skills --skill dart-use-pattern-matching安装后在 Claude Code 中输入/dart-use-pattern-matching确认已加载。
详细介绍
目录
模式选择策略
根据目标数据结构应用不同的模式匹配策略:
- JSON 验证与解构:使用 Map 和 List 模式,在单个步骤中同时验证嵌套结构并将值绑定到局部变量。
- 多个返回值:从函数返回 Record,并使用 Record 模式将命名值或位置值直接解构到作用域内的变量。
- 代数数据类型(ADT):将
sealed类层次结构与 Switch 表达式中的 Object 模式结合,以利用编译时穷尽性检查。 - 数值范围与逻辑检查:在 Switch case 中组合关系模式(
>=、<等)与逻辑与(&&)或逻辑或(||)运算符。 - 守卫子句:使用
when关键字断言无法仅通过静态模式表达的动态条件。
Switch 表达式与 Switch 语句
根据操作场景选择合适的 Switch 结构:
Switch 表达式
- 适用场景:Switch 结构必须求值并返回单个值时。
- 语法:
final result = switch (value) { pattern => expression, _ => fallback }; - 规则:每个 case 都必须求值为一个表达式(不能是语句或代码块)。所有 case 都必须穷尽(由编译器检查)。不支持隐式贯穿执行。
Switch 语句
- 适用场景:Switch 结构必须执行副作用、语句或复杂代码块时。
- 语法:
switch (value) { case pattern: // statements break; // Implicitly breaks, but can be added explicitly } - 规则:空 case 会贯穿执行。非空 case 不会隐式贯穿执行。
核心模式语法
了解并应用标准 Dart 3+ 模式语法:
- 逻辑或(
||):组合模式。任一模式匹配成功即视为匹配。两个分支必须定义完全相同的变量集合。 - 逻辑与(
&&):两个模式都匹配成功时才匹配。分支不得定义重叠的变量。 - 关系模式:使用比较运算符对常量进行求值(例如
> 100、!= 0)。 - 强制转换(
as):在解构时断言类型转换(类型检查失败时会抛出异常)。 - 空值检查(
?):筛除空值,并将变量绑定为其非空基类型。 - 空值断言(
!):断言值非空(值为空时会抛出异常)。 - List 模式:匹配指定长度的数组(例如
[var first, var second])。使用剩余元素(...)忽略列表末尾的元素。 - Map 模式:匹配键值目标(例如
{'id': var id})。忽略未明确匹配的键。 - Object 模式:匹配类实例并提取属性值(例如
User(:final name))。
工作流:设计模式匹配逻辑
按照此清单实现清晰的模式匹配结构:
- 确定结构:识别源数据是 Enum、Sealed Class 层次结构、Record 还是原始 JSON。
- 选择 Switch 结构:赋值时选择 Switch 表达式,执行副作用时选择 Switch 语句。
- 定义 case 绑定:构造明确的 Map、List 或 Object 模式,将所需字段提取到作用域内的变量中。
- 添加守卫:使用
when表达式进行条件边界检查。 - 验证穷尽性:使用 sealed 类或 enum 时,让编译器检查穷尽性。使用开放类型时,添加通配符
_作为回退。 - 验证编译器输出:运行
dart analyze,确保没有未处理的 case 或类型不匹配。
示例
JSON 验证与解析
使用映射解构,一步完成结构验证和值提取。
void processPayload(Map<String, dynamic> payload) {
if (payload case {'status': 'success', 'data': [String title, int count]}) {
print('Product: $title, Inventory: $count');
} else {
print('Invalid payload structure received');
}
}
密封类穷尽匹配
使用密封类,在执行领域逻辑时强制进行穷尽的编译时验证。
sealed class NetworkState {}
class NetworkIdle extends NetworkState {}
class NetworkLoading extends NetworkState {}
class NetworkSuccess extends NetworkState {
final String response;
NetworkSuccess(this.response);
}
class NetworkFailure extends NetworkState {
final String error;
NetworkFailure(this.error);
}
// Compiler guarantees all sub-states are handled without requiring a default fallback
String getStatusMessage(NetworkState state) {
return switch (state) {
NetworkIdle() => 'Waiting to connect...',
NetworkLoading() => 'Loading data...',
NetworkSuccess(:final response) => 'Data loaded: $response',
NetworkFailure(:final error) => 'Failed: $error',
};
}
记录解构与交换
// Destructuring a positional and named return record:
(String name, {int age}) getUser() => ('Alice', age: 30);
void main() {
final (name, age: userAge) = getUser();
print('$name is $userAge years old');
// Value swapping without temp variables:
var (x, y) = (1, 2);
(y, x) = (x, y);
}
评论
支持 Markdown