What is Null Safety?
Null safety is a feature in Dart that helps you avoid null reference errors – those dreaded runtime crashes where you try to use a variable that unexpectedly contains null. With null safety, variables are non‑nullable by default, meaning they cannot contain null unless you explicitly allow it. This moves null checks from runtime to compile time, making your code more robust and predictable.
Nullable vs Non‑Nullable Types
In Dart, every type now has a nullable counterpart. By default, types are non‑nullable. To allow a variable to hold null, add a ? after the type.
The ? Operator (Nullable Type)
Adding ? to a type creates a nullable version. You can assign either a value of that type or null.
The ! Operator (Null Assertion)
Use the ! operator when you are absolutely sure that a nullable variable is not null at that point. It asserts that the value is non‑null and returns it as a non‑nullable type. If you're wrong, it throws a runtime error – so use it sparingly.
The late Keyword
Sometimes you know a variable will be initialised before it's used, but not immediately at declaration. Use late to tell Dart to trust you. If you fail to initialise it before use, you get a runtime error.
late is also useful for lazy initialisation – expensive computations that should only run when the variable is first accessed.
Null‑Aware Operators
Dart provides several operators to handle nullable values safely and concisely.
?. – Safe Member Access
Access a property or method only if the object is not null; otherwise, the expression evaluates to null.
?? – If‑Null Operator
Returns the left operand if it's not null; otherwise returns the right operand.
??= – Null‑Aware Assignment
Assigns a value to a variable only if that variable is currently null. If it's already non‑null, the assignment is ignored.
Type Promotion
Dart's flow analysis can promote nullable types to non‑nullable within certain scopes after a null check, allowing you to use them safely without the ! operator.
This also works with is checks and logical operators like && and ||.
Working with Collections
Collections can also be nullable, and their elements can be nullable. Be careful with type arguments.
Migration from Pre‑Null Safety
If you have existing Dart code without null safety, you can migrate using dart migrate. The tool helps you add ?, late, and other null safety features. After migration, run dart pub get and fix any remaining analysis issues.
Best Practices
- Prefer non‑nullable types – only make a variable nullable if
nullis a meaningful state.
- Prefer non‑nullable types – only make a variable nullable if
- **Use
latefor non‑nullable variables that are initialised after construction (e.g., dependency injection).
- **Use
- Avoid overusing
!– prefer safe access (?.) or explicit null checks with promotion.
- Avoid overusing
- Use
??for default values – it's clearer than a ternary with a null check.
- Use
- Take advantage of type promotion – write code that naturally checks for null before use.
- Be explicit with collection types – decide whether the collection itself can be null or its elements.
Complete Example
Key Takeaways
- Null safety eliminates null reference errors at compile time.
- Types are non‑nullable by default; add
?to allow null.
- Types are non‑nullable by default; add
- Use
latefor variables initialised after declaration.
- Use
- Null‑aware operators (
?.,??,??=) provide safe and concise handling.
- Null‑aware operators (
- Type promotion lets you use nullable variables as non‑nullable after checks.
- Migrate existing code with
dart migrate.
- Migrate existing code with