Bringing Primary Constructors to Dart

WaltPurvis1 pts1 comments

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...

dart constructors language syntax primary syntactic

Related Articles