Here's what frustrates me about programming languages. Something obvious doesn't work for years. Then the team fixes it and announces it like a feature. Dart 3.12 just did exactly that with private named parameters. But let's be fair. At least they fixed it.
Programming language teams have a peculiar talent for celebrating the removal of their own mistakes. You spend years working around a limitation that never made sense. Then one day the changelog arrives, and there it is: "New Feature!" What they mean is: "We finally stopped blocking something that should have worked from day one."
Dart 3.12 is a solid release. Private named parameters, primary constructors, AI integration, and Firebase Functions in Dart. Some of it is genuinely new. Some of it is long overdue. Let me walk you through what actually matters.
The Boilerplate Tax Nobody Asked For

Dart has this neat trick with constructors. You write this.fieldName and the field initializes itself. No redundant assignments. Clean and simple.
Until you want a private field with a named parameter.
Privacy in Dart means slapping an underscore at the start. _secretValue is private. publicValue is public. Straightforward enough. The problem? Before version 3.12, the compiler threw a tantrum when you tried combining these two concepts:
class UserSession {
final String _token;
final int _expiresAt;
// Dart 3.11: "Absolutely not"
UserSession({required this._token, required this._expiresAt});
}
Instead you had to write this nonsense:
class UserSession {
final String _token;
final int _expiresAt;
UserSession({required String token, required int expiresAt})
: _token = token,
_expiresAt = expiresAt;
}
Look at that initializer list. What does it accomplish? It strips underscores. That's it. Three lines of code exist solely to remove a single character from variable names.
In a codebase with 150 model classes, this adds up to thousands of lines that serve no purpose except satisfying a compiler limitation. The hubris of language designers sometimes astounds me. They create arbitrary restrictions, watch developers suffer for years, then pat themselves on the back when they finally relent.
What Changed in 3.12
Dart 3.12 finally lets you write what should have worked from day one:
class UserSession {
final String _token;
final int _expiresAt;
UserSession({required this._token, required this._expiresAt});
}
The compiler automatically maps _token to a public parameter called token. You call the constructor like normal:
void main() {
var session = UserSession(token: 'abc123xyz', expiresAt: 1735689600);
print(session);
}
Inside the class you access _token. Outside you use token. The compiler handles the translation.
Revolutionary? No. Should this have worked since Dart 2.0? Absolutely. But I'll take a late fix over no fix.
Primary Constructors: Borrowed From Kotlin, Finally

Google went further and added something Kotlin developers have enjoyed for years. Primary constructors let you define a class in a single line.
The traditional approach looks like this:
class Coordinate {
final double lat;
final double lng;
Coordinate(this.lat, this.lng);
}
Four lines for a class with two fields. With primary constructors:
class Coordinate(final double lat, final double lng);
One line. Parameters in the class header become fields automatically.
You can also define additional constructors inside the class body:
class Player {
String username;
new() : username = 'Guest';
new named(this.username);
}
class Admin extends Player;
Classes without a body end with a semicolon. Looks weird at first. Saves typing in practice.
Here's the catch. This feature is experimental. You need to enable it manually:
dart run --enable-experiment=primary-constructors bin/main.dart
My recommendation? Try it in a side project. Don't ship it to production. Google has a track record of abandoning experimental features without warning. Remember Dart 1.0's optional typing? The original Angular? I've been burned before.
Genkit: Dart's Play for the AI Market

Google released Genkit Dart. It's a framework for building apps with language models. This answers the question every Flutter developer has been asking: "Do I need to learn Python just to add AI to my app?"
Genkit supports multiple models. Gemini, Claude, OpenAI. You can switch between them without rewriting your integration:
import 'package:genkit/genkit.dart';
import 'package:genkit_google_genai/genkit_google_genai.dart';
import 'package:genkit_anthropic/genkit_anthropic.dart';
void main() async {
final assistant = Genkit(plugins: [googleAI(), anthropic()]);
final geminiResult = await assistant.generate(
model: googleAI.gemini('gemini-flash-latest'),
prompt: 'Explain recursion in one sentence',
);
final claudeResult = await assistant.generate(
model: anthropic.model('claude-opus-4.6'),
prompt: 'What causes memory leaks in mobile apps',
);
}
The framework includes a local interface for testing prompts. Useful because debugging AI applications without proper tooling is pure misery.
Will Genkit disrupt the market? I doubt it. Python owns machine learning and that won't change anytime soon. But if you're already committed to Dart and Flutter, this is a reasonable option. You don't need to maintain two separate tech stacks just to make a chatbot answer user questions.
As Andrej Karpathy recently admitted, even AI experts feel behind on keeping up with the pace of change. Having AI tools in your existing language stack removes one more barrier.
Want to optimize your AI coding costs? The AI Coding Cost Optimization shows you how to save money and get better outcomes. Use code MEDIUMSAVES20 for 20% off. Subscribers to the Vibe Coding Newsletter save 50%
Firebase Functions in Dart: One Language, One Truth
For years, extending a Flutter app with backend logic meant this: write models in Dart for the frontend, then rewrite them in JavaScript for Cloud Functions. Two languages. Two definitions of identical structures. Double the chance for bugs.
Now you can write Cloud Functions in Dart. Share a package containing your models between frontend and backend. One language. One source of truth.
Dart compiles ahead of time, so serverless functions start fast. Cold starts plague serverless architectures. Node.js needs time to warm up. Dart is ready immediately. 食得鹹魚抵得渴.
The feature is experimental. Don't migrate critical infrastructure yet. But for greenfield projects, it's worth considering.
Agentic Hot Reload: Marketing Speak With Actual Value
Google added something called "Agentic Hot Reload". Sounds like buzzword soup. The concept is actually useful.
You're using an AI agent for coding. Gemini, Copilot, whatever. The agent modifies your code. Normally you'd manually trigger hot reload to see changes. Now the Dart MCP server does it automatically.
Agent changes a widget. App reloads. You see the result. No copying URIs. No switching windows.
Does this change everything? No. Does it save 30 seconds per iteration? Yes. Those seconds compound over a workday.
Performance Diagnostics You Can Actually Use
The new dart info record-performance command lets you record traces from the Dart Analysis Server. If your IDE lags during autocomplete, you can capture data and attach it to a GitHub issue.
This is smart from Google. Performance problems are nearly impossible to debug without real data from actual user machines. Instead of guessing, they're asking for help. I respect that approach.
Git LFS Support in Pub
dart pub now natively supports Git Large File Storage. If your dependency stores large files in a repository, pub fetches them automatically.
dependencies:
trained_models:
git: https://github.com/company/ml-weights.git
Just have git lfs installed. No extra configuration needed.
If you're building full-stack SaaS systems and want to level up your architecture skills, check out the Scaled: Architecting Scalable Enterprise Angular Applications guide
Breaking Changes Worth Knowing
A few things that might bite you during upgrade:
- The
isAmethod indart:js_interopmoved fromJSAnyUtilityExtensiontoNullableObjectUtilExtension. If you referenced the extension name directly, your code won't compile dart pub cache repairnow only fixes packages from your currentpubspec.lockby default. Want the old behavior? Add the--allflag- New lint
simple_directive_pathsflags overly complex import paths. Fix them in bulk withdart fix --code=simple_directive_paths --apply
The Bottom Line
Dart 3.12 is a solid release. Private named parameters should have existed from the begining. Primary constructors look promising but I'm waiting for stability.
The AI integration signals where Google sees the future. Is some of it hype? Definitely. Is it useful for certain projects? Also yes.
Update with dart upgrade or flutter upgrade. Test before deploying to production. And don't enable experimental features in code that needs to work six months from now.
Google has a habit of shipping experiments and walking away. Protect yourself accordingly.
Sources
- Dart 3.12 Release Notes, Google Dart Team, May 2026
Related Reading
- Even AI Experts Feel Behind: What Andrej Karpathy's Confession Means for Programmers - How even the best in the field struggle to keep up with AI's pace
- Future Software Engineer Career: Complete Roadmap - Planning your engineering career in the age of AI
- Bill Gates on Programmer Jobs in 2026: It Will Be Bumpy, Enjoy the Ride - What industry leaders predict for developers
What's your take on Dart's direction? Are you excited about primary constructors, or do you think Google should focus on stabilizing existing features first?
