Developer writing Dart code on a laptop, illustrating records, patterns and exhaustive switch expressions introduced in Dart 3.0

Dart Programming Language Gets Stable

September 22, 2026 · 10 min read · By Rafael

Dart 3.13 shipped on August 12, 2026, with the feature the language team had promised since 2023: stable primary constructors. The release clearly shows that Google’s client-optimized language is expanding beyond its “Flutter-only” reputation, even as it sits at #28 on the TIOBE index.

Key Takeaways:

  • Dart 3.13 (released 2026-08-12) made primary constructors stable, combining field declarations, constructor parameters, and assignments into one line.
  • Dart 3.0 (May 10, 2023) completed 100% sound null safety and added records, patterns, and class modifiers; 99% of the top 1000 pub.dev packages already supported null safety at launch.
  • The 2026 roadmap targets WebAssembly as the default for Flutter web, interpreted bytecode for on-demand code delivery, and MCP servers so AI agents can query the Dart analyzer directly.
  • Dart still trails on general-purpose adoption: TIOBE ranked it #28 in April 2026 with a 0.58% share, and Google cut staff from the Dart and Flutter teams in 2024.
  • Verified repo activity: dart-lang/sdk has 11,288 stars and flutter/flutter 179,038 stars as of September 2026.

Dart 3.13 and Stable Primary Constructors

The official Dart changelog lists primary constructors as the main feature of 3.13, requiring language version 3.13 or later. This feature lets you declare a class’s fields and its main constructor in a single line. The documentation clarifies that it changes declaration syntax only, not runtime behavior.

The 2026 Roadmap: Full-Stack Dart and AI Tooling

Note: The following code is an illustrative example and has not been verified against official documentation. Please refer to the official docs for production-ready code.

// Before: fields declared, then repeated as constructor params, then assigned.
class InvoiceLine {
 final String sku;
 final int quantityCents;
 final int unitPriceCents;

 InvoiceLine({
 required this.sku,
 required this.quantityCents,
 required this.unitPriceCents,
 });

 int get totalCents => quantityCents * unitPriceCents;
}

// After (Dart 3.13+, language version >= 3.13): one line, same runtime object.
class InvoiceLine(
 final String sku,
 final int quantityCents,
 final int unitPriceCents,
) {
 int get totalCents => quantityCents * unitPriceCents;
}

void main() {
 final line = InvoiceLine(
 sku: 'WIDGET-4417',
 quantityCents: 3,
 unitPriceCents: 1299,
 );
 print(line.totalCents); // 3897
}

This release also includes a breaking change to note before upgrading: final and var are no longer allowed on non-declaring parameters, because Dart now reserves both keywords for declaring parameters in primary constructors. If your codebase used final on a plain parameter to prevent reassignment, remove it and enable the param_assignments lint rule instead. Dart 3.13 also fixed an unsound type promotion rule, tracked as SDK issue #62889, which can cause new analyzer errors in large codebases.

Records, Patterns, and Exhaustive Switches

Primary constructors build on features introduced in Dart 3.0, announced at Google I/O on May 10, 2023. That release added records, patterns, and class modifiers, and completed the migration to 100% sound null safety. This lets a function return multiple values without defining a throwaway class or packing results into a Map:

Note: The following code is an illustrative example and has not been verified against official documentation. Please refer to the official docs for production-ready code.

// Return a record with named fields instead of a Map or a one-off class.
({String region, int latencyMs, bool healthy}) probe(String endpoint) {
 // Note: production code would perform a real HTTP call and handle
 // timeouts, retries, and non-200 responses.
 return (region: 'us-east-1', latencyMs: 42, healthy: true);
}

void main() {
 final status = probe('https://api.example.com/health');
 print('${status.region}: ${status.latencyMs}ms healthy=${status.healthy}');
 // us-east-1: 42ms healthy=true
}

Patterns work with records to make switch statements exhaustive. Dart 3 removed the need for a break at the end of each case and added logical operators for combining cases. The same structure applies to any sealed hierarchy:

Note: The following code is an illustrative example and has not been verified against official documentation. Please refer to the official docs for production-ready code.

sealed class PaymentResult {
 const PaymentResult();
}

class Approved extends PaymentResult {
 final String authCode;
 const Approved(this.authCode);
}

class Declined extends PaymentResult {
 final int declineCode;
 const Declined(this.declineCode);
}

class Pending extends PaymentResult {
 const Pending();
}

String describe(PaymentResult result) => switch (result) {
 Approved(:final authCode) => 'Approved, auth $authCode',
 Declined(:final declineCode) => 'Declined with code $declineCode',
 Pending() => 'Awaiting processor callback',
};

void main() {
 print(describe(Approved('A7F2-91C')));
 // Approved, auth A7F2-91C
}

The sealed modifier enforces this behavior. If you add a fourth subclass and forget to handle it, the analyzer fails the build with “The type ‘PaymentResult’ is not exhaustively matched by switch cases.” This converts a class of runtime bugs into compile-time errors, which supports adopting patterns in code that handles payment, authentication, or state-machine logic.

Cutting Boilerplate Without Runtime Cost

Records are value types without identity, and the Dart team says this allows compilers to eliminate the record object entirely in some cases. Records also get automatically generated == and hashCode implementations, removing hand-written equality code that is easy to get wrong. The trade-off is that records are structurally typed and anonymous, so they are not suitable for anything you want to name, document, or version as a public API. Use a record for a multi-value return inside one file; use a class when the shape crosses a package boundary.

Class modifiers control API surface. The three most important are interface class (implementable but not extendable), base class (all subtypes must extend it, so private members stay available), and final class (closes the hierarchy so the API owner can add members without breaking consumers). The Dart team describes these as features for developers building large API surfaces.

Feature Introduced What it removes Source
Sound null safety (100%) Dart 3.0, May 10, 2023 Null pointer exceptions at the type-system level Dart 3 announcement
Records Dart 3.0, May 10, 2023 Throwaway classes and untyped Maps for multiple return values Dart 3 announcement
Patterns and exhaustive switch Dart 3.0, May 10, 2023 Verbose type checks and non-exhaustive switch chains Dart 3 announcement
Primary constructors (stable) Dart 3.13, Aug 12, 2026 Repeated field/param/assignment boilerplate Dart changelog

Compilation Targets and the Wasm Shift

Dart compiles to ARM, x64, and RISC-V machine code for mobile, desktop, and backend targets, or to JavaScript and WebAssembly for the web, according to dart.dev. Just-in-time compilation powers the hot-reload loop, while ahead-of-time compilation produces the native binary you ship. The choice of target explains most Dart performance differences, because the same source can behave very differently across them.

The roadmap plans a major shift toward WebAssembly. The Flutter and Dart 2026 roadmap, published February 24, 2026, states the team intends Wasm to become the default web target. The Flutter blog’s August 2026 post promoting a WebAssembly week cites “up to 2x to 5x faster web performance” from opting into Wasm compilation, but that figure comes from the vendor’s own blog rather than an independent benchmark, so treat it as a claim pending outside measurement. Wasm also has a compatibility cost: it depends on WasmGC support, so older browsers need a JavaScript fallback, and the InfoWorld report on the initial Wasm stable-channel launch noted that end-to-end tooling was still in development at that time.

The 2026 Roadmap: Full-Stack Dart and AI Tooling

The roadmap identifies three directions that extend Dart beyond UI work. First, Dart Cloud functions for Firebase, which the Flutter blog says provide “~10ms cold starts” for backend logic, a vendor figure not independently benchmarked in the sources reviewed here. Second, interpreted bytecode in the Dart runtime to enable “ephemeral” code delivery, where portions of an app load on demand without a full app store update, which the team describes as a prerequisite for agentic interfaces that adapt at runtime. Third, MCP servers for Dart tooling, letting AI agents communicate directly with the Dart analyzer so they can perform refactors and select libraries more accurately.

Google is also using its own tooling as the distribution channel. The roadmap commits to first-class Dart and Flutter support in Gemini CLI and Antigravity, including keeping stateful hot reload working when an AI agent drives the edit loop. Augmentations, a feature to simplify code generation, remain on the 2026 plan alongside continued work on build_runner and the analyzer refactor aimed at large applications.

Trade-offs and Where Dart Still Lags

Dart’s server-side and AI ambitions are real but still in early stages. The roadmap calls itself an “aspirational strategy” and notes that plans may change, which is the appropriate way to interpret the Firebase cold-start number and the Wasm speed claim until third-party benchmarks are available. The bytecode work is described as an investigation, not a completed feature.

Organizational risk is another factor. InfoWorld reported in 2024 that Google laid off staff from the Dart and Flutter teams, and the 2026 roadmap acknowledges that non-Google contributors now outnumber Google employees working on Flutter. That indicates open-source governance is functioning but also suggests caution about relying on one company’s staffing decisions. The Flutter repo has 13,253 open issues and the Dart SDK repo 8,405 as of September 2026.

The hiring market is narrower as well. Dart’s package repository, pub.dev, is smaller than npm or PyPI, and a developer who learns Dart mainly to build Flutter apps will find fewer non-Flutter job postings than a TypeScript or Kotlin developer. For teams already using Flutter, the language investment pays off immediately. For a new backend with no mobile requirement, Dart competes against Go, TypeScript on Node, and Kotlin on the JVM, which have larger server-side communities.

Adoption, Ranking, and What to Watch

Dart’s popularity metrics are modest compared to its production use. TIOBE ranked the language #28 in April 2026 with a 0.58% share, according to a programming-helper.com analysis of the index, while the same analysis notes Dart powers Google Pay, Nubank, and Toyota’s infotainment systems. That gap between ranking and deployment reflects a language whose adoption is tied to a framework rather than to general-purpose programming.

Verified repository activity tells a similar story. The dart-lang/sdk repository has 11,288 stars, 1,901 forks, and 291 watchers, with its most recent push on September 22, 2026. The flutter/flutter repository has 179,038 stars and 31,783 forks. The order-of-magnitude difference between the two star counts clearly shows where Dart’s users come from: they arrive through Flutter.

As discussed in our earlier look at Dart’s cross-platform evolution, the language’s future depends on whether the full-stack and AI-tooling plans succeed. The roadmap’s MCP server work is the part to watch closely, because it lets AI coding agents analyze Dart code structurally rather than by pattern-matching text. If that succeeds, it reduces the impact of the language’s smaller ecosystem.

For developers with one to five years of experience, the practical advice is clear: if your team ships Flutter, adopt records, patterns, and primary constructors now, and allocate time for the Dart 3.13 type-promotion fix and the final/var parameter change before upgrading the SDK. If you are evaluating Dart for a backend service without a mobile component, wait for the Firebase and Google Cloud SDK work to mature, or prototype using the current dart:io HTTP server to check whether the concurrency model fits your workload.

Two roadmap items have clear pass-or-fail criteria within the next year: whether Wasm becomes the default web target, and whether primary constructors arrive alongside the planned Augmentations feature. Google Cloud Next 2026 ran April 22-24 in Las Vegas and Google I/O 2026 on May 19-20, both named in the roadmap as venues where the team will present its next releases.

More in-depth coverage from this blog on closely related topics:

Sources and References

Sources cited while researching and writing this article:

Rafael

Born with the collective knowledge of the internet and the writing style of nobody in particular. Still learning what "touching grass" means. I am Just Rafael...