Dart Dot Shorthand
last modified July 10, 2026
Dot shorthand syntax (.member) lets us write more concise Dart code by
omitting the type when the compiler can infer it from context. It provides a
clean alternative to writing the full ContextType.member when accessing
enum values, static members, or constructors.
Dot shorthands require a language version of at least 3.10.
In essence, dot shorthands allow an expression to start with one of the following:
- Identifier
.myValue - Constructor
.new() - Constant creation
const .myValue()
Dot shorthands with enums
A primary use case for dot shorthands is with enums, especially in assignments and switch statements, where the enum type is obvious from context.
enum Status { none, running, stopped, paused }
enum LogLevel { debug, info, warning, error }
String colorCode(LogLevel level) {
return switch (level) {
.debug => 'gray',
.info => 'blue',
.warning => 'orange',
.error => 'red',
};
}
void main() {
// Dot shorthand in variable assignment
Status currentStatus = .running;
print(currentStatus);
// Dot shorthand in switch expression
String warnColor = colorCode(.warning);
print(warnColor);
}
The compiler infers .running to mean Status.running
and .warning to mean LogLevel.warning from the
context type. In the switch expression, the cases use dot shorthand to match
each enum value concisely.
$ dart main.dart Status.running orange
Dot shorthands with named constructors
Dot shorthands are useful for invoking named constructors or factory constructors. This syntax also works when providing type arguments to a generic class's constructor.
class Point {
final double x, y;
const Point(this.x, this.y);
const Point.origin() : x = 0, y = 0;
factory Point.fromList(List<double> list) {
return Point(list[0], list[1]);
}
}
void main() {
// Dot shorthand on a named constructor
Point origin = .origin();
// Dot shorthand on a factory constructor
Point p1 = .fromList([1.0, 2.0]);
print('origin: (${origin.x}, ${origin.y})');
print('p1: (${p1.x}, ${p1.y})');
}
The compiler infers .origin() as Point.origin() and
.fromList() as Point.fromList() from the context
type of the variable declaration.
$ dart main.dart origin: (0, 0) p1: (1.0, 2.0)
Dot shorthands with unnamed constructors
The .new dot shorthand provides a concise way to call an unnamed
constructor of a class. This is useful for assigning fields or variables where
the type is already explicitly declared.
Without dot shorthands:
class Task {
final String name;
final int priority;
Task(this.name, {this.priority = 0});
}
void main() {
Task task1 = Task('Write code');
Task task2 = Task('Review PR', priority: 1);
List<int> numbers = List<int>.filled(5, 0);
print('${task1.name}: ${task1.priority}');
print('${task2.name}: ${task2.priority}');
print(numbers);
}
With dot shorthands:
class Task {
final String name;
final int priority;
Task(this.name, {this.priority = 0});
}
void main() {
Task task1 = .new('Write code');
Task task2 = .new('Review PR', priority: 1);
List<int> numbers = .filled(5, 0);
print('${task1.name}: ${task1.priority}');
print('${task2.name}: ${task2.priority}');
print(numbers);
}
The .new syntax replaces the explicit class name when calling the
unnamed constructor. This is particularly effective for cleaning up repetitive
field initializers in classes like Flutter's State.
$ dart main.dart Write code: 0 Review PR: 1 [0, 0, 0, 0, 0]
Dot shorthands with static members
We can use dot shorthand syntax to call static methods or access static fields and getters.
void main() {
// Dot shorthand on static method
int httpPort = .parse('80');
// Dot shorthand on static field
BigInt bigIntZero = .zero;
// Dot shorthand in a chain
String lowerH = .fromCharCode(72).toLowerCase();
print('Port: $httpPort');
print('BigInt zero: $bigIntZero');
print('Lower: $lowerH');
}
The compiler infers .parse('80') as int.parse('80'),
.zero as BigInt.zero, and
.fromCharCode(72) as String.fromCharCode(72) from
the context types.
$ dart main.dart Port: 80 BigInt zero: 0 Lower: h
Dot shorthands in constant expressions
Dot shorthands can be used within a constant context if the member being
accessed is a compile-time constant. This is common for enum values and
invoking const constructors.
enum Status { none, running, stopped, paused }
class Point {
final double x, y;
const Point(this.x, this.y);
const Point.origin() : x = 0.0, y = 0.0;
}
void main() {
// Dot shorthand for enum value in const context
const Status defaultStatus = .running;
// Dot shorthand for const named constructor
const Point myOrigin = .origin();
// Dot shorthand in const collection literal
const List<Point> keyPoints = [.origin(), .new(1.0, 1.0)];
print(defaultStatus);
print('(${myOrigin.x}, ${myOrigin.y})');
print(keyPoints.length);
}
In constant expressions, the dot shorthand resolves to compile-time constants
such as enum values or const constructors.
$ dart main.dart Status.running (0.0, 0.0) 2
Asymmetric equality checks
The == and != operators have a special rule for dot
shorthands. When dot shorthand syntax is used directly on the right-hand side
of an equality check, Dart uses the static type of the left-hand side to
determine the class or enum for the shorthand.
enum Color { red, green, blue }
String describe(Color color) {
if (color == .green) return 'green like grass';
if (color != .blue) return 'some other color';
return 'blue like sky';
}
void main() {
Color myColor = Color.red;
print(describe(myColor));
print(describe(Color.green));
print(describe(Color.blue));
}
In color == .green, the compiler uses the type of color
(Color) to infer .green as Color.green.
The dot shorthand must be on the right-hand side of the equality operator.
$ dart main.dart some other color green like grass blue like sky
Rules and limitations
Dot shorthands rely on a clear context type, which leads to several rules and limitations.
Clear context type required
The compiler must be able to infer the type from context. If the context type is ambiguous or missing, the code will not compile.
void main() {
// OK: context type is clear from variable declaration
int value = .parse('42');
// ERROR: expression statement cannot start with '.'
// .parse('42');
// OK: chaining works when context type is clear
String lowerH = .fromCharCode(72).toLowerCase();
print('$value, $lowerH');
}
Expression statements cannot start with dot
To avoid potential parsing ambiguities, an expression statement is not allowed
to begin with a . token. Dot shorthands only work in contexts
where there is a clear target type, such as variable declarations, return
statements, or parameter passing.
Limited union type handling
For nullable types (T?), we can access static members of
T, but not of Null. For FutureOr<T>,
we can access static members of T, but not of the
Future class itself.
Best practices
- Use with enums: Dot shorthands are most effective with enums in assignments and switch expressions.
- Clear context: Ensure the context type is unambiguous for the compiler to infer correctly.
- Equality checks: Place dot shorthands on the right-hand side of
==and!=operators. - Constructors: Use
.new()for unnamed constructors when the type is already declared. - Const contexts: Dot shorthands work well in constant expressions with enum values and const constructors.
Source
Dart Dot Shorthands Documentation
This tutorial covered Dart's dot shorthand syntax with practical examples demonstrating its use with enums, constructors, static members, and constant expressions.
Author
List all Dart tutorials.