Skip to content

prefer_shorthands_with_enums

v0.3.0 Warning Fix Shorthand Patterns

Flags explicit enum prefixes (e.g., LogLevel.debug) when the enum type can be inferred from context and a dot shorthand (.debug) would suffice. This applies to switch cases, switch expressions, variable declarations with explicit types, comparisons, default parameter values, and return expressions.

When the expected enum type is already known from context, repeating the enum name adds noise without adding clarity. Dot shorthands are shorter, reduce visual clutter in switch statements and widget trees, and are the idiomatic Dart style in type-inferred positions.

See also: Dart language - Enums

enum LogLevel { debug, warning }
void example(LogLevel? e) {
switch (e) {
case LogLevel.debug:
print(e);
}
final v = switch (e) {
LogLevel.debug => 1,
_ => 2,
};
final LogLevel defaultLevel = LogLevel.debug;
if (e == LogLevel.debug) {}
}
void fn({LogLevel value = LogLevel.debug}) {}
LogLevel levelForBad() => LogLevel.debug;
enum LogLevel { debug, warning }
void example(LogLevel? e) {
switch (e) {
case .debug:
print(e);
}
final v = switch (e) {
.debug => 1,
_ => 2,
};
final LogLevel defaultLevel = .debug;
if (e == .debug) {}
// Collection in an untyped position — no context type, so no lint:
expect(rankings, equals([LogLevel.debug]));
// An explicit type argument does provide context:
takes(<LogLevel>[.debug]);
}
void fn({LogLevel value = .debug}) {}
LogLevel levelForBad() => .debug;
// Explicit prefix is fine when type cannot be inferred:
Object asObject() => LogLevel.debug;

Collection literals need a real context type

Section titled “Collection literals need a real context type”

A dot shorthand is only legal where the compiler has a downward context type. Inside a collection literal that sits in a dynamic or Object? position, there is none — the analyzer infers the literal’s type upward from the elements themselves:

// Not reported: `equals(Object? expected)` gives the list no context type.
expect(rankings, equals([LogLevel.debug]));
// Writing `.debug` here would fail to compile:
// error: A dot shorthand can't be used where there is no context type.
// (dot_shorthand_missing_context)

The rule reports inside a collection only when the element type comes from a genuine context — a typed variable, a typed parameter, or an explicit type argument:

void collectionExamples() {
final List<LogLevel> list = [.debug]; // reported
takes(items: [.debug]); // reported (typed named argument)
takes(<LogLevel>[.debug]); // reported (explicit type argument)
final Map<LogLevel, String> map = {.debug: 'a'}; // key has context
}

The same applies to a generic parameter whose type argument is solved from the argument. The analyzer reports List<LogLevel> there, but only because it inferred T from the element itself — so there is no downward context and the shorthand would not compile:

class Box<T> {
const Box({required this.items});
final List<T> items;
}
void boxExamples() {
// Not reported: `T` is inferred, so there is no context type.
Box(items: const [LogLevel.debug]);
// Reported: the type argument imposes a context.
Box<LogLevel>(items: const [.debug]);
}

This rule is in the opinionated preset, so it is on with preset: opinionated, or by name:

many_lints.yaml
rules:
prefer_shorthands_with_enums: true

To turn it off again:

many_lints.yaml
rules:
prefer_shorthands_with_enums: false

To keep the rule on but skip certain paths, use per-rule exclude.