Guidelines for using modern Dart features (v3.0 - v3.10) such as Records,
Extension Types, Class Modifiers, Wildcards, Digit Separators, Null-Aware
Elements, and Dot Shorthands.
Installs into .claude/skills of the current project.
Are you the author of Dart Modern Features?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kevmoo-dart-modern-features)
---
name: dart-modern-features
description: |-
Guidelines for using modern Dart features (v3.0 - v3.10) such as Records,
Extension Types, Class Modifiers, Wildcards, Digit Separators, Null-Aware
Elements, and Dot Shorthands.
key_features:
- Records & Extension Types
- Class Modifiers & Wildcards
- Null-aware elements & Dot shorthands
---
# Dart Modern Features
## 1. When to use this skill
Use this skill when:
- Writing or reviewing Dart code targeting Dart 3.0 or later.
- Refactoring legacy Dart code to use modern, concise, and zero-cost features
such as records, extension types, class modifiers, null-aware collection
elements, dot shorthands, and digit separators.
- Looking for idiomatic ways to handle multiple return values or zero-cost
domain wrappers.
For pattern matching, switch expressions, and list/map/split destructuring, use
**[dart-use-pattern-matching]**. For converting closed class hierarchies into
exhaustive `sealed` types, use **[dart-seal-type-hierarchies]**.
### When NOT to use (Abstention Guardrails)
Do NOT apply modern features or refactor code when:
- **SDK Constraint < 3.0.0**: The package's `pubspec.yaml` specifies an SDK
constraint that supports Dart 2.x (e.g., `sdk: '>=2.19.0 <4.0.0'`).
Refactoring to Dart 3 features will introduce syntax errors for Dart 2 users.
- **Public API Records with > 3 Fields**: Records work well for 2–3 return
values or internal tuples, but complex public API payloads are clearer and
more extensible as dedicated classes or extension types.
## Discovery
To find candidates for modernization:
### Null-Aware Elements
Search for collection `if` statements checking for null:
- **Regex**: `if\s*\(\w+\s*!=\s*null\)\s*\w+`
### Digit Separators
Search for long numbers without separators:
- **Regex**: `\b\d{6,}\b` (Matches numbers with 6 or more digits).
## 2. Features
### 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
}
```
### Class Modifiers
Use class modifiers (`final`, `base`, `interface`, `sealed`) to restrict how
classes can be subtyped outside their defining library:
- `interface class`: External libraries may `implement`, but cannot `extend`.
- `base class`: External libraries may `extend`, but cannot `implement`
(preserving private implementation invariants).
- `final class`: External libraries can neither `extend` nor `implement`.
- `sealed class`: Closed family of subtypes within the same library enabling
exhaustive switching (see **[dart-seal-type-hierarchies]**).
**Avoid:** Leaving internal implementation classes open to arbitrary external
subclassing or interface implementation when invariants must be enforced.
```dart
class TokenStore {
void save(String token) {}
}
```
**Prefer:** Declaring explicit subtyping capabilities with class modifiers.
```dart
final class TokenStore {
void save(String token) {}
}
```
### 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;
}
```
### 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;
```
### 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');
}
```
### 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'];
```
### 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;
```
## Related Skills
- **[dart-use-pattern-matching]**: Authoritative guide for Dart 3 pattern
matching, switch expressions, and list/map/`String.split()` destructuring.
- **[dart-seal-type-hierarchies]**: Converting closed class hierarchies into
`sealed` types for exhaustive switching.
- **[dart-best-practices]**: General code style and foundational Dart idioms
that predate or complement the modern syntax features.
[dart-use-pattern-matching]:
https://github.com/dart-lang/skills/blob/main/skills/dart-use-pattern-matching/SKILL.md
[dart-seal-type-hierarchies]:
https://github.com/kevmoo/dash_skills/blob/main/skills/dart-seal-type-hierarchies/SKILL.md
[dart-best-practices]:
https://github.com/kevmoo/dash_skills/blob/main/skills/dart-best-practices/SKILL.md