Source profileQuality 86/100

evanca/flutter-ai-rules/skills/dart-3-updates/SKILL.md

dart-3-updates

Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring values, or modernizing pre-Dart-3 code.

Source repository stars
604
Declared platforms
0
Static risk flags
0
Last source update
2026-08-04
Source checked
2026-08-04

Decision brief

What it does—and where it fits

Apply Dart 3 language features — branches, patterns, pattern types, and records — correctly and idiomatically.

Best for

  • Writing or refactoring switch statements or if-else chains.
  • Creating new data-holding classes and deciding between sealed classes, records, or plain classes.
  • Destructuring values from maps, lists, records, or objects.

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/evanca/flutter-ai-rules --skill "skills/dart-3-updates"
Safe inspection promptEditorial

Inspect the Agent Skill "dart-3-updates" from https://github.com/evanca/flutter-ai-rules/blob/b294a77b68b5508f8d3151fb93d87ed9622d2ff1/skills/dart-3-updates/SKILL.md at commit b294a77b68b5508f8d3151fb93d87ed9622d2ff1. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    5. Migration Workflow

    When modernizing pre-Dart-3 code, follow these steps:

    When modernizing pre-Dart-3 code, follow these steps:Replace wrapper classes used solely for returning multiple values with records.Run dart analyze to confirm exhaustiveness and type safety after each change.
  2. 02

    Step 1 — Replace if-else chains with switch expressions

    Review the “Step 1 — Replace if-else chains with switch expressions” section in the pinned source before continuing.

    Review and apply the “Step 1 — Replace if-else chains with switch expressions” source section.
  3. 03

    Step 2 — Convert abstract class hierarchies to sealed classes

    Review the “Step 2 — Convert abstract class hierarchies to sealed classes” section in the pinned source before continuing.

    Review and apply the “Step 2 — Convert abstract class hierarchies to sealed classes” source section.
  4. 04

    Step 3 — Use destructuring for multiple return values

    Replace wrapper classes used solely for returning multiple values with records.

    Replace wrapper classes used solely for returning multiple values with records.
  5. 05

    Step 4 — Validate

    Run dart analyze to confirm exhaustiveness and type safety after each change.

    Run dart analyze to confirm exhaustiveness and type safety after each change.

Permission review

Static risk signals and limitations

No configured static risk pattern was detected

This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score86/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars604SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
evanca/flutter-ai-rules
Skill path
skills/dart-3-updates/SKILL.md
Commit
b294a77b68b5508f8d3151fb93d87ed9622d2ff1
License
MIT
Collected
2026-08-04
Default branch
main
View the original SKILL.md

Dart 3 Updates Skill

Apply Dart 3 language features — branches, patterns, pattern types, and records — correctly and idiomatically.

When to Use

Use this skill when:

  • Writing or refactoring switch statements or if-else chains.
  • Creating new data-holding classes and deciding between sealed classes, records, or plain classes.
  • Destructuring values from maps, lists, records, or objects.
  • Modernizing pre-Dart-3 code to use patterns, exhaustiveness checks, or switch expressions.

1. Branches

if / if-case

// Standard if
if (score >= 90) {
  grade = 'A';
} else if (score >= 80) {
  grade = 'B';
} else {
  grade = 'C';
}

// if-case: match and destructure against a single pattern
if (pair case [int x, int y]) {
  print('$x, $y');
}
  • if conditions must evaluate to a bool.
  • In if-case, variables declared in the pattern are scoped to the matching branch.
  • If the pattern does not match, control flows to the else branch (if present).

switch statements

switch (command) {
  case 'quit':
    quit();
  case 'start' || 'begin': // logical-or pattern
    startGame();
  default:
    print('Unknown command');
}
  • Each matched case body executes and jumps to the end — break is not required.
  • Non-empty cases can end with continue, throw, or return.
  • Use default or _ to handle unmatched values.
  • Empty cases fall through; use break to prevent fallthrough in an empty case.
  • Use continue with a label for non-sequential fallthrough.
  • Use logical-or patterns (case a || b) to share a body between cases.

switch expressions

final color = switch (shape) {
  Circle() => 'red',
  Square() => 'blue',
  _ => 'unknown',
};
  • Omit case; use => for bodies; separate cases with commas.
  • Default must use _ (not default).
  • Produces a value.

Exhaustiveness

  • Dart checks exhaustiveness in switch statements and expressions at compile time.
  • Use default/_, enums, or sealed types to satisfy exhaustiveness.
sealed class Shape {}
class Circle extends Shape {}
class Square extends Shape {}

// Dart knows all subtypes — no default needed:
String describe(Shape s) => switch (s) {
  Circle() => 'circle',
  Square() => 'square',
};

Guard clauses

switch (point) {
  case (int x, int y) when x == y:
    print('Diagonal: $x');
  case (int x, int y):
    print('$x, $y');
}
  • Add when condition after a pattern to further constrain matching.
  • Usable in if-case, switch statements, and switch expressions.
  • If the guard is false, execution proceeds to the next case.

2. Patterns

Patterns represent the shape of a value for matching and destructuring.

Uses

// Variable declaration
var (a, [b, c]) = ('str', [1, 2]);

// Variable assignment (swap)
(b, a) = (a, b);

// for-in loop destructuring
for (final MapEntry(:key, :value) in map.entries) { ... }

// switch / if-case (see Branches section)
  • Wildcard _ ignores parts of a matched value.
  • Rest elements (...) in list patterns ignore remaining elements.
  • Case patterns are refutable: if no match, execution continues to the next case.
  • Destructured values in a case become local variables scoped to that case body.

Object patterns

var Foo(:one, :two) = myFoo;

JSON / nested data validation

if (data case {'user': [String name, int age]}) {
  print('$name, $age');
}

3. Pattern Types

PatternSyntaxDescription
Logical-orp1 || p2Matches if any branch matches. All branches must bind the same variables.
Logical-andp1 && p2Matches if both match. Variable names must not overlap.
Relational== c, < c, >= cCompares value to a constant. Combine with && for ranges.
Castsubpattern as TypeAsserts type, then matches inner pattern. Throws if type mismatch.
Null-checksubpattern?Matches non-null; binds non-nullable type.
Null-assertsubpattern!Matches non-null or throws. Use in declarations to eliminate nulls.
Constant42, 'str', const Foo()Matches if value equals the constant.
Variablevar name, final Type nameBinds matched value to a new variable. Typed form only matches the declared type.
Wildcard_, Type _Matches any value without binding.
Parenthesized(subpattern)Controls precedence.
List[p1, p2]Matches lists by position. Length must match unless a rest element is used.
Rest element..., ...restMatches arbitrary-length tails or collects remaining elements.
Map{'key': subpattern}Matches maps by key. Missing keys throw StateError.
Record(p1, p2), (x: p1, y: p2)Matches records by shape; field names can be omitted if inferred.
ObjectClassName(field: p)Matches by type and destructures via getters. Extra fields ignored.
  • Use parentheses to group lower-precedence patterns.
  • All pattern types can be nested and combined.

4. Records

// Create
var record = ('first', a: 2, b: true, 'last');

// Type annotation
({int a, bool b}) namedRecord;

// Access
print(record.$1);   // positional: 'first'
print(record.a);    // named: 2
  • Records are anonymous, immutable, fixed-size aggregates.
  • Each field can have a different type (heterogeneous).
  • Fields are accessed via built-in getters ($1, $2, .name); no setters.
  • Two records are equal if they have the same shape and equal field values.
  • hashCode and == are automatically defined.

Multiple return values

(String name, int age) userInfo(Map<String, dynamic> json) {
  return (json['name'] as String, json['age'] as int);
}

var (name, age) = userInfo(json);
// Named fields:
final (:name, :age) = userInfo(json);

Records vs. data classes

Use a record when:

  • Returning multiple values from a single function (small, one-time use).
  • Grouping a few values locally with no reuse across the codebase.
  • You need structural equality with no additional behavior.

Use a class when:

  • The type is reused across multiple files or features.
  • You need methods, encapsulation, inheritance, or copyWith.
  • The type is part of a public API or long-lived data model.
  • Changing the shape must be caught by the type system across the codebase.

Other best practices

  • Use typedef for record types to improve readability and maintainability.
  • Changing a record type alias does not guarantee type safety across the codebase — only classes provide full abstraction.

5. Migration Workflow

When modernizing pre-Dart-3 code, follow these steps:

Step 1 — Replace if-else chains with switch expressions

// Before (pre-Dart 3)
String label;
if (status == Status.loading) {
  label = 'Loading...';
} else if (status == Status.success) {
  label = 'Done';
} else {
  label = 'Error';
}

// After (Dart 3)
final label = switch (status) {
  Status.loading => 'Loading...',
  Status.success => 'Done',
  Status.error => 'Error',
};

Step 2 — Convert abstract class hierarchies to sealed classes

// Before
abstract class Result {}
class Success extends Result { final String data; Success(this.data); }
class Failure extends Result { final String error; Failure(this.error); }

// After — enables exhaustive switch
sealed class Result {}
final class Success extends Result { const Success(this.data); final String data; }
final class Failure extends Result { const Failure(this.error); final String error; }

Step 3 — Use destructuring for multiple return values

Replace wrapper classes used solely for returning multiple values with records.

Step 4 — Validate

Run dart analyze to confirm exhaustiveness and type safety after each change.


Alternatives

Compare before choosing

Computed 10042,968

coreyhaines31/marketingskills

ab-testing

When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program

Computed 10023,781

alirezarezvani/claude-skills

app-store-optimization

App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

Computed 1004,922

dotnet/skills

migrate-vstest-to-mtp

Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing

Computed 100165

JasonColapietro/suede-creator-skills

suede-ab-testing

Suede-owned experimentation discipline for hypotheses, sample sizing, test duration, significance, and repeatable experiment programs. Use when comparing variants, deciding whether a result is reliable, or building an experiment backlog and cadence. NOT FOR: analytics instrumentation (use suede-analytics), post-click conversion diagnosis (use suede-site-alchemy), or writing the variant copy itself (use suede-copy).