mcpField
D
dart-language-syntax

dart-language-syntax

github.com/dart-lang开发53273 次安装2 周前更新
代码仓库

关于 dart-language-syntax

面向 Dart 开发者和编码 Agent 的技能,指导编写和现代化惯用 Dart 代码,涵盖状态、函数、记录、模式匹配与泛型。

主要功能

  1. 01选择 var、final 和 const
  2. 02使用 tear-off 与生成器
  3. 03通过记录返回并解构数据
  4. 04使用模式匹配和 switch 表达式
  5. 05编写类型安全的泛型代码

适用场景

  1. 01现代化旧版 Dart 代码
  2. 02用记录替代元组类
  3. 03使用模式匹配验证 JSON
  4. 04用 switch 表达式重构条件逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dart-lang/skills --skill dart-language-syntax

安装后在 Claude Code 中输入/dart-language-syntax确认已加载。

详细介绍

编写符合 Dart 惯用风格的代码

目录

变量和状态管理

使用严格的可变性和类型推断规则管理状态和变量声明。

  • 优先使用 var: 当赋值类型显而易见时,局部变量使用 var(例如,var name = 'Bob';)。如果无法从初始化表达式中立即判断类型,则使用显式类型。
  • 确保不可变性: 对于初始化后不应重新赋值的变量,使用 final。对于编译时常量,以及用于创建规范化不可变对象实例的情况,使用 const。
  • 善用 late: 使用 late 修饰符,将非空变量的初始化延迟到首次使用时,尤其适用于开销较大的计算,或需要访问 this 才能初始化的情况。
  • 使用通配符: 使用通配符变量 _(需要 Dart 3.7+),在局部声明、闭包或模式匹配中丢弃未使用的值,且不会触发未使用变量警告。

函数和闭包

让函数结构具备最大的可组合性,并尽可能减少样板代码。

  • 使用箭头语法: 使用 => 运算符简化单表达式函数。
  • 优先使用方法 tear-off: 直接传递函数引用(tear-off),而不是用多余的匿名闭包包装它们(例如,使用 list.forEach(print),而不是 list.forEach((e) => print(e)))。
  • 实现生成器: 使用 sync* 延迟生成 Iterable 序列,使用 async* 生成 Stream 序列。使用 yield 生成值,或使用 yield* 委托给其他生成器。
  • 定义命名参数: 对于带有布尔标志或多个参数的函数,使用命名参数 ({required Type name}),以提高调用处的可读性。

记录和模式匹配

使用记录和模式消除样板数据类及复杂条件逻辑。

  • 返回多个值: 使用记录 (Type, Type) 从函数返回多个值,而无需定义专用类。
  • 解构赋值: 掌握模式匹配,直接将记录、列表和对象解构到局部变量中。
  • 使用 switch 表达式: 使用 switch 表达式替代复杂的 if-else 链。借助逻辑或模式(||)和守卫子句(when),让多个分支共享逻辑。
  • 以声明式方式验证 JSON: 使用映射和列表模式,同时验证结构、检查类型,并从动态 JSON 负载中提取数据。

泛型和类型安全

确保集合和自定义组件具备类型安全性和可复用性。

  • 实现泛型: 使用 <T> 为类、方法和集合设置参数化类型。
  • 限制类型参数: 使用 extends 限定泛型类型(例如,使用 <T extends Object> 强制非空,或使用 <T extends BaseWidget>)。
  • 使用 F-Bounds: 当类必须与其自身确切类型的实例交互时,实施自引用类型约束(例如,class Node<T extends Node<T>>)。
  • 扩展功能: 使用扩展方法和扩展类型,为现有的泛型类或具体类添加实用函数,而无需创建子类。

工作流:重构为符合 Dart 惯用风格的代码

使用此清单,将旧版 Dart 代码升级为符合现代 Dart 3+ 标准的惯用代码。

  • 任务进度:变量现代化
    • 对于一目了然的局部赋值,使用 var 替代显式类型。
    • 如果可变的 var 声明从未被重新赋值,则将其改为 final。
    • 将未使用的参数 __ 或 ___ 替换为标准的 _ 通配符。
  • 任务进度:控制流与返回
    • 使用原生 Record (T1, T2) 替代自定义的“Tuple”或“Pair”类。
    • 将冗余闭包重构为函数/方法 tear-off。
    • 将只包含一条语句的函数体改为箭头 => 语法。
  • 任务进度:模式匹配集成
    • 如果要从对象中提取多个字段,请使用对象解构:var User(:name, :age) = user;。
    • 如果要验证嵌套 JSON,请使用映射/列表模式替代 is 检查和手动类型转换。
    • 如果要对代数数据类型(密封类)进行分支处理,请将 switch 语句转换为穷尽式 switch 表达式。
  • 运行验证器 -> 检查错误 -> 修复: 运行 dart analyze 和 dart format。解决与类型提升或穷尽性相关的任何 lint 错误。

示例

解构多个返回值(Record)

输入(旧版):

class UserInfo {
  final String name;
  final int age;
  UserInfo(this.name, this.age);
}

UserInfo fetchUser() => UserInfo('Dash', 10);
final info = fetchUser();
print(info.name);

输出(惯用写法):

(String, int) fetchUser() => ('Dash', 10);

// Destructure directly into final variables
final (name, age) = fetchUser();
print(name);
声明式 JSON 验证(模式)

输入(旧版):

if (json is Map<String, Object?> && json.containsKey('user')) {
  var user = json['user'];
  if (user is List<Object> && user.length == 2 && user[0] is String && user[1] is int) {
    var name = user[0] as String;
    var age = user[1] as int;
    print('User $name is $age');
  }
}

输出(惯用写法):

if (json case {'user': [String name, int age]}) {
  print('User $name is $age');
}
Switch 表达式与守卫子句

实现:

sealed class Shape {}
class Square implements Shape { final double length; Square(this.length); }
class Circle implements Shape { final double radius; Circle(this.radius); }

double calculateArea(Shape shape) => switch (shape) {
  Square(length: var l) when l > 0 => l * l,
  Circle(:var radius) when radius > 0 => 3.14159 * radius * radius,
  _ => 0.0, // Fallback for invalid dimensions
};
带泛型的扩展方法

实现:

extension IterableExtensions<T> on Iterable<T> {
  /// Returns the first element matching the predicate, or null.
  T? firstWhereOrNull(bool Function(T) test) {
    for (final element in this) {
      if (test(element)) return element;
    }
    return null;
  }
}

评论

支持 Markdown