dart-modern-features

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dart Modern Features

Dart 现代特性

1. When to use this skill

1. 何时使用本技能

Use this skill when:
  • Writing or reviewing Dart code targeting Dart 3.0 or later.
  • Refactoring legacy Dart code to use modern, concise, and safe features.
  • Looking for idiomatic ways to handle multiple return values, deep data extraction, or exhaustive checking.
在以下场景使用本技能:
  • 编写或审查基于Dart 3.0及以上版本的代码时。
  • 重构旧版Dart代码以使用现代、简洁且安全的特性时。
  • 寻找处理多返回值、深度数据提取或穷尽检查的惯用方法时。

2. Features

2. 特性介绍

Records

Records

Use records as anonymous, immutable, aggregate structures to bundle multiple objects without defining a custom class. Prefer them for returning multiple values from a function or grouping related data temporarily.
Avoid: Creating a dedicated class for simple multiple-value returns.
dart
class UserResult {
  final String name;
  final int age;
  UserResult(this.name, this.age);
}

UserResult fetchUser() {
  return UserResult('Alice', 42);
}
Prefer: Using records to bundle types seamlessly on the fly.
dart
(String, int) fetchUser() {
  return ('Alice', 42);
}

void main() {
  var user = fetchUser();
  print(user.$1); // Alice
}
使用Records作为匿名、不可变的聚合结构,无需定义自定义类即可捆绑多个对象。推荐在函数返回多个值或临时分组相关数据时使用。
应避免: 为简单的多值返回创建专用类。
dart
class UserResult {
  final String name;
  final int age;
  UserResult(this.name, this.age);
}

UserResult fetchUser() {
  return UserResult('Alice', 42);
}
推荐: 使用Records动态无缝捆绑类型。
dart
(String, int) fetchUser() {
  return ('Alice', 42);
}

void main() {
  var user = fetchUser();
  print(user.$1); // Alice
}

Patterns and Pattern Matching

Patterns and Pattern Matching

Use patterns to destructure complex data into local variables and match against specific shapes or values. Use them in
switch
,
if-case
, or variable declarations to unpack data directly.
Avoid: Manually checking types, nulls, and keys for data extraction.
dart
void processJson(Map<String, dynamic> json) {
  if (json.containsKey('name') && json['name'] is String &&
      json.containsKey('age') && json['age'] is int) {
    String name = json['name'];
    int age = json['age'];
    print('$name is $age years old.');
  }
}
Prefer: Combining type-checking, validation, and assignment into a single statement.
dart
void processJson(Map<String, dynamic> json) {
  if (json case {'name': String name, 'age': int age}) {
    print('$name is $age years old.');
  }
}
使用Patterns将复杂数据解构为局部变量,并匹配特定的结构或值。可在
switch
if-case
或变量声明中使用,直接解包数据。
应避免: 手动检查类型、空值和键以提取数据。
dart
void processJson(Map<String, dynamic> json) {
  if (json.containsKey('name') && json['name'] is String &&
      json.containsKey('age') && json['age'] is int) {
    String name = json['name'];
    int age = json['age'];
    print('$name is $age years old.');
  }
}
推荐: 将类型检查、验证和赋值合并为单个语句。
dart
void processJson(Map<String, dynamic> json) {
  if (json case {'name': String name, 'age': int age}) {
    print('$name is $age years old.');
  }
}

Switch Expressions

Switch Expressions

Use switch expressions to return a value directly, eliminating bulky
case
and
break
statements.
Avoid: Using switch statements where every branch simply returns or assigns a value.
dart
String describeStatus(int code) {
  switch (code) {
    case 200:
      return 'Success';
    case 404:
      return 'Not Found';
    default:
      return 'Unknown';
  }
}
Prefer: Returning the evaluated expression directly using the
=>
syntax.
dart
String describeStatus(int code) => switch (code) {
  200 => 'Success',
  404 => 'Not Found',
  _ => 'Unknown',
};
使用Switch Expressions直接返回值,消除冗余的
case
break
语句。
应避免: 在每个分支仅返回或赋值的场景使用switch语句。
dart
String describeStatus(int code) {
  switch (code) {
    case 200:
      return 'Success';
    case 404:
      return 'Not Found';
    default:
      return 'Unknown';
  }
}
推荐: 使用
=>
语法直接返回求值表达式。
dart
String describeStatus(int code) => switch (code) {
  200 => 'Success',
  404 => 'Not Found',
  _ => 'Unknown',
};

Class Modifiers

Class Modifiers

Use class modifiers (
sealed
,
final
,
base
,
interface
) to restrict how classes can be used outside their defines library. Prefer
sealed
for defining closed families of subtypes to enable exhaustive checking.
Avoid: Using open
abstract
classes when the set of subclasses is known and fixed.
dart
abstract class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) {
  if (r is Success) return 'OK';
  if (r is Failure) return 'Error';
  return 'Unknown';
}
Prefer: Using
sealed
to guarantee to the compiler that all cases are covered.
dart
sealed class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) => switch(r) {
  Success() => 'OK',
  Failure() => 'Error',
};
使用类修饰符(
sealed
final
base
interface
)限制类在其定义库之外的使用方式。推荐使用
sealed
定义封闭的子类型家族,以支持穷尽检查。
应避免: 在子类集合已知且固定的场景使用开放的
abstract
类。
dart
abstract class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) {
  if (r is Success) return 'OK';
  if (r is Failure) return 'Error';
  return 'Unknown';
}
推荐: 使用
sealed
向编译器保证所有情况都已覆盖。
dart
sealed class Result {}

class Success extends Result {}
class Failure extends Result {}

String handle(Result r) => switch(r) {
  Success() => 'OK',
  Failure() => 'Error',
};

Extension Types

Extension Types

Use extension types for a zero-cost wrapper around an existing type. Use them to restrict operations or add custom behavior without runtime overhead.
Avoid: Allocating new wrapper objects just for domain-specific logic or type safety.
dart
class Id {
  final int value;
  Id(this.value);
  bool get isValid => value > 0;
}
Prefer: Using extension types which compile down to the underlying type at runtime.
dart
extension type Id(int value) {
  bool get isValid => value > 0;
}
使用Extension Types作为现有类型的零成本包装器。可用于限制操作或添加自定义行为,且无运行时开销。
应避免: 仅为领域特定逻辑或类型安全分配新的包装对象。
dart
class Id {
  final int value;
  Id(this.value);
  bool get isValid => value > 0;
}
推荐: 使用Extension Types,其在运行时会编译为底层类型。
dart
extension type Id(int value) {
  bool get isValid => value > 0;
}

Digit Separators

Digit Separators

Use underscores (
_
) in number literals strictly to improve visual readability of large numeric values.
Avoid: Long number literals that are difficult to read at a glance.
dart
const int oneMillion = 1000000;
Prefer: Using underscores to separate thousands or other groupings.
dart
const int oneMillion = 1_000_000;
在数字字面量中使用下划线(
_
)以提升大数值的视觉可读性。
应避免: 使用难以一眼读取的长数字字面量。
dart
const int oneMillion = 1000000;
推荐: 使用下划线分隔千位或其他分组。
dart
const int oneMillion = 1_000_000;

Wildcard Variables

Wildcard Variables

Use wildcards (
_
) as non-binding variables or parameters to explicitly signal that a value is intentionally unused.
Avoid: Inventing clunky, distinct variable names to avoid "unused variable" warnings.
dart
void handleEvent(String ignoredName, int status) {
  print('Status: $status');
}
Prefer: Explicitly dropping the binding with an underscore.
dart
void handleEvent(String _, int status) {
  print('Status: $status');
}
使用通配符(
_
)作为非绑定变量或参数,明确表示该值是有意未使用的。
应避免: 为避免"未使用变量"警告而创建笨拙的独特变量名。
dart
void handleEvent(String ignoredName, int status) {
  print('Status: $status');
}
推荐: 使用下划线明确放弃绑定。
dart
void handleEvent(String _, int status) {
  print('Status: $status');
}

Null-Aware Elements

Null-Aware Elements

Use null-aware elements (
?
) inside collection literals to conditionally include items only if they evaluate to a non-null value.
Avoid: Using collection
if
statements for simple null checks.
dart
var names = [
  'Alice',
  if (optionalName != null) optionalName,
  'Charlie'
];
Prefer: Using the
?
prefix inline.
dart
var names = ['Alice', ?optionalName, 'Charlie'];
在集合字面量中使用空感知元素(
?
),仅当项的求值结果为非空时才条件性包含该元素。
应避免: 对简单的空检查使用集合
if
语句。
dart
var names = [
  'Alice',
  if (optionalName != null) optionalName,
  'Charlie'
];
推荐: 使用
?
前缀内联处理。
dart
var names = ['Alice', ?optionalName, 'Charlie'];

Dot Shorthands

Dot Shorthands

Use dot shorthands to omit the explicit type name when it can be confidently inferred from context, such as with enums or static fields.
Avoid: Fully qualifying type names when the type is obvious from the context.
dart
LogLevel currentLevel = LogLevel.info;
Prefer: Reducing visual noise with inferred shorthand.
dart
LogLevel currentLevel = .info;
使用Dot Shorthands省略显式类型名称,当类型可从上下文可靠推断时(如枚举或静态字段)。
应避免: 在类型从上下文可明显推断时仍完全限定类型名称。
dart
LogLevel currentLevel = LogLevel.info;
推荐: 使用推断简写减少视觉干扰。
dart
LogLevel currentLevel = .info;

Related Skills

相关技能

  • dart-best-practices
    : General code style and foundational Dart idioms that predate or complement the modern syntax features.
  • dart-best-practices
    : 通用代码风格和基础Dart惯用写法,早于或补充现代语法特性。