New and Factory Keywords in Class Headers: Dart 3.13's Concise Constructor Syntax
Dart 3.13 lets you replace the repeated class name with new or factory in constructor declarations. Here's how the concise syntax works.
Published on • October 20, 2026
AI Assistant

Dart 3.13, released August 12, 2026, made primary constructors stable, but tucked into the same release is a smaller language change that removes a different kind of boilerplate: you no longer need to repeat the class name in every constructor declaration. Instead of writing Point(...) or factory Point.zero(), you can write new(...) or factory zero() directly in the class body. The Dart 3.13 announcement calls it “concise syntax for constructors,” and it pairs naturally with primary constructors to keep class declarations short.
The problem: repeating the class name everywhere
Every Dart class repeats its own name in each constructor:
class Point {
int x;
int y;
Point(this.x, this.y);
Point.origin() : x = 0, y = 0;
factory Point.fromList(List<int> coords) => Point(coords[0], coords[1]);
}
The class name in each declaration carries no information — you’re already inside the class body, and the compiler knows which class you’re extending. It’s pure noise that grows with every constructor you add.
Using new in place of the class name
Dart 3.13 lets you replace the type name of an unnamed generative constructor with the new keyword:
class Point {
int x;
int y;
new(this.x, this.y);
origin() : x = 0, y = 0;
}
Named constructors already don’t repeat their own name after the dot — you drop the class-name prefix entirely, leaving just origin(). The behavior is identical to the verbose form; this changes only how the declaration reads.
Using factory for factory constructors
Factory constructors get the same treatment. Replace factory Point.fromList(...) with factory fromList(...):
class Point {
int x;
int y;
new(this.x, this.y);
origin() : x = 0, y = 0;
factory fromList(List<int> coords) => Point(coords[0], coords[1]);
}
The factory keyword stays because it communicates something meaningful — this constructor may return an existing instance, a subtype, or a cached object rather than allocating a new one.
Empty bodies can end with ;
Concise constructor syntax arrives with another small cleanup: an empty declaration body ({}) can be written as a semicolon. So a constructor with only an initializer list goes from:
origin() : x = 0, y = 0 {}
to:
origin() : x = 0, y = 0;
This isn’t limited to constructors — class-like declarations with empty bodies, such as a class whose fields are all set by a primary constructor, accept ; too. That’s what enables the one-line style class Point(final int x, final int y);.
The lint that enforces the concise style
Dart 3.13 also shipped the unnecessary_type_name_in_constructor lint, which flags constructor declarations that still repeat the type name and suggests replacing them with new. The companion lint empty_container_bodies nudges you toward ; over empty {}. Both have automated fixes, so you can adopt the style across an existing codebase with dart fix:
dart fix --apply
As with all language-versioned changes, you’ll only see the new formatting and lint behavior once your package’s language version is at least 3.13, which means an SDK lower constraint of 3.13.0 in your pubspec.yaml.
Concise syntax applies to const constructors too. A class like:
class Color {
final int value;
const Color(this.value);
const Color.red() : value = 0xFFFF0000;
}
becomes:
class Color {
final int value;
const new(this.value);
const red() : value = 0xFFFF0000;
}
The const modifier keeps its position before the constructor; new replaces only the type name.
One gotcha: a method named factory
There’s a parsing edge case worth knowing. If you declare a method literally named factory with no return type — factory() {} — Dart 3.13 parses it as a concise factory constructor, not a method. If you genuinely need a method with that name (an unlikely scenario, but legal Dart), give it an explicit return type such as void factory() {}.
Where this fits with primary constructors
Concise constructor syntax works with or without primary constructors. A class with a primary constructor can’t also have other non-redirecting generative in-body constructors — the primary constructor must run on every instantiation — but factory constructors and named constructors backed by factories remain available. The two features complement each other: primary constructors compress field declarations and the main constructor into the header, and concise syntax keeps any remaining in-body constructors from re-expanding the class.
If you’re still on an older SDK, the concise syntax is a low-stakes reason to upgrade — it removes real repetition without changing runtime behavior, and the IDE refactorings landing alongside it (covered in a follow-up post) do most of the migration work for you. The feature is language-versioned, so it activates once your package’s SDK lower bound reaches 3.13; until then, your existing constructor declarations stay valid and the analyzer won’t suggest the shorter forms. That also makes it easy to adopt per-package: libraries you actively touch can move to the concise style on their next edit while untouched code keeps compiling unchanged.