Lesson 4 / 25
Sound Null Safety
Use nullable and non-nullable types, null-aware operators, late and required correctly.
Null errors caught at compile time
Since Dart 3, sound null safety is always on: a type like String can never be null, and you add ? to allow null (String?). The analyser tracks nullability and refuses to let you call methods on a possibly-null value until you handle the null case, and type promotion means that after if (name != null) the variable is treated as non-nullable inside the block (for local variables). Null-aware operators: ?. (call only if not null), ?? (default value), ??= (assign if null), and the spread ...? for nullable collections. The ! operator asserts a value is not null and throws at run time if it is, so use it sparingly. late marks a non-nullable variable or field that is initialised later, for example in initState in Flutter, with a run-time check on first read. required makes named parameters mandatory. Because the system is sound, the compiler can trust non-nullable types and generate faster code, and a whole class of crashes disappears.
Nullable and non-nullable types
A non-nullable type always holds a value; a nullable type adds the possibility of null that must be handled.
Handling nullable values
Promotion, null-aware operators and required named parameters.
class Customer {
Customer({required this.name, this.phone, this.address});
final String name;
final String? phone; // may be null
final Address? address;
}
class Address {
Address(this.city);
final String city;
}
String contactLine(Customer c) {
final city = c.address?.city ?? 'City not set'; // null-aware access + default
final phone = c.phone;
if (phone != null) {
return '${c.name}, $city, ${phone.replaceAll(' ', '')}'; // promoted to String
}
return '${c.name}, $city';
}
void main() {
final c = Customer(name: 'Asha', address: Address('Pune'));
print(contactLine(c));
Map<String, int> stock = {'pen': 10};
final pens = stock['pen'] ?? 0; // map lookups return int?
stock['ink'] ??= 5; // assign only if absent
}Every ! is a promise you might break
value! throws if value is null at run time. Before reaching for !, try a local variable with a null check (which enables promotion), ?? or an early return.
Quick check: In Dart 3, what does the type String (without ?) guarantee?
- It may be null
- It is always empty
- It can never be null
- It is dynamic
Answer
It can never be null — With sound null safety, non-nullable types cannot hold null.