Null safety removes a whole class of crashes, and every Dart and Flutter API is written with it.
In Dart 3, types are non-nullable by default: a String can never be null. Add ? to allow it: String? nickname;. Nullable variables start as null; non-nullable locals must be assigned before use.
Null-aware operators:
a ?? b—aunless it is null, thenb.x ??= value— assign only ifxis null.user?.name— null ifuseris null, otherwise the property.value!— assert non-null; throws if it is null. Use sparingly.
Flow analysis promotes types: after if (name != null), name is treated as String inside the block. The same happens after an early return or throw. Promotion only works for local variables and private final fields, because a public field or getter could return something different the next time.
late declares a non-nullable variable that is initialized later: late final String token;. Reading it before assignment throws. late with an initializer makes it lazy: the expression runs on first access.
Since Dart 3.8, collection literals support null-aware elements: [?maybeItem] adds the item only if it is non-null.
The guarantee is sound: once your program and its dependencies are null-safe, a non-nullable expression can never evaluate to null at run time.
Example
String greet(String? name) {
if (name == null) return 'Hello, guest';
return 'Hello, ${name.toUpperCase()}'; // promoted to String
}
class Config {
late final String apiKey; // set later, once
late final int heavy = compute(); // lazy: runs on first read
int compute() { print('computing'); return 42; }
}
void main() {
print(greet(null)); // Hello, guest
print(greet('ana')); // Hello, ANA
String? city;
print(city?.length ?? 0); // 0
city ??= 'Oslo';
print(city.length); // 4 (promoted after ??=)
final c = Config()..apiKey = 'k-1';
print(c.heavy); // computing / 42
String? tag;
print([1, ?tag].length); // 1 (null-aware element)
}Remember
- Types are non-nullable unless marked
? - Prefer
??,?.and null checks over! - Flow analysis promotes local variables after a null check
Watch out for
- Expecting a class field to promote after
if (field != null)— copy it to a local first.