Bringing Primary Constructors to Dart | The Dart Blog
Skip to main content
dart.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.
Learn more<br>OK, got it
menu<br>close
asteriskOverview
docsDocs
newsmodeBlog
publicCommunity
play_lessonLearn Dart
downloadGet Dart
Bringing Primary Constructors to Dart
An inside look at the design decisions, trade-offs, and syntactic sugar behind adding primary constructors to Dart 3.13.
Bob Nystrom
Aug 20, 2026 · 22 min read
rss_feed
share
content_copyCopy link
Share on X
Share on Bluesky
Share on LinkedIn
Bringing primary constructors to Dart
(AI disclosure: I wrote every sentence of this myself—including the em<br>dashes.)
My favorite feature in Dart 3.13 is<br>primary constructors.<br>Getting there took a lot of time and iteration before the language team had a<br>design we felt was solid. Since many of you have been patiently waiting for<br>this feature, I thought it would be worth writing about some of the challenges<br>we worked through to bring this large syntax change to Dart.
On syntactic sugar
Users have been asking for something like primary constructors for years.<br>It's a highly desired feature, which is kind of strange when you think about<br>it. Primary constructors don't let you do anything you can't already do in<br>Dart. They're just a different—hopefully better!—syntax for what you can<br>already express.
In the 1960s, Peter Landin coined the term "syntactic sugaring" to refer to<br>layering some textual niceties on top of a more fundamental but unpleasant<br>language. Today, we tend to use the term more like a noun and call features<br>like these "syntactic sugar".
The immortal enemy of every programming language is complexity.<br>Even the tiniest feature must be designed,<br>specified, implemented, tested, and documented.<br>The cost is large. I think of complexity in a language like weight in an<br>airplane. Some amount of it is necessary for the thing to work,<br>but you have to be careful to not add weight unnecessarily or risk the whole<br>apparatus not getting off the ground.
From that angle, syntactic sugar seems like a bad idea.<br>It's additional complexity with no additional utility.<br>Even worse, once we add it, we pass complexity onto our users too.<br>Now they have to choose which syntax to use each time they are trying to<br>express something.
When are these kinds of features ever a good idea?<br>(I admit I feel some need to justify this because so much of my work over the<br>past several years has been adding these kinds of features to Dart.)<br>I think syntactic sugar can carry its weight in a couple of ways:
The new way is simply better
Despite our somewhat robotic affect and fondness for<br>EBNF, we<br>language designers are human and make mistakes.<br>Further, we are always learning, the ecosystem we serve is constantly<br>discovering new ways to make software,<br>and user expectations drift over time.
When Dart was first designed, you had to use an explicit new keyword to call<br>a constructor. This was deliberate to be familiar to users coming from C++,<br>Java, JavaScript, and other languages.<br>The intent was to make it clearer in the code when a call allocates a new<br>object. As garbage collectors got better and users got more comfortable with<br>automatic memory management, most users found new to be more noise than<br>signal.
(Also, honestly, Dart has always undermined that signal by supporting<br>factory constructors.<br>A factory constructor can return some previously created object even when you<br>invoke it with new.)
In Dart 2.0, we shipped a language change that allowed you to omit the new<br>keyword (and const in many places) when calling a constructor.<br>We still support the old syntax, so this language change is essentially<br>syntactic sugar, but we really only kept the old syntax around for backwards<br>compatibility.
We always want you to use the new shorter syntax.<br>We shipped tooling to automatically remove<br>the unnecessary new keywords, and have<br>a lint that reminds you<br>when you forget. The old syntax is effectively deprecated and over time you<br>see it less and less. If you're new to Dart,<br>you may not have even realized we supported using new in constructor calls.
That means the complexity for supporting constructor calls both with and<br>without new is low. There is a transition cost for existing users to learn<br>the new syntax. But new users will mostly just learn the new way and never<br>encounter the old. There's little cognitive load when choosing between the two<br>syntaxes because you simply always use the new one (and our tools will gently<br>remind you if you don't).
Short of having a time machine to go back and do it right the first time,<br>this is the next best thing we can do to fix a mistake in the language.
The syntax can be much better for a common use case
For the first several years of its public existence,<br>Dart had no support for enum declarations.<br>The language didn't let you write:
dart<br>enum Color { red, blue, yellow }
content_copy
Instead, you had to...