What does the late keyword do in Dart, and what's a common mistake with it?
Short Answer
late tells the compiler a non-nullable variable will definitely be assigned before use, even though it can't verify that at compile time — deferring the null-safety check to runtime, where accessing it before assignment throws a LateInitializationError.
Sound null safety normally requires the compiler to prove a non-nullable variable is initialized before use. Sometimes that's genuinely not knowable at compile time — e.g. a controller initialized in initState() rather than at declaration. late is an escape hatch: you promise the variable will be set before any read, and the compiler trusts you instead of proving it.
The common mistake is using late as a workaround to silence a null-safety error without actually guaranteeing initialization happens first — this converts a compile-time safety net into a runtime crash (LateInitializationError) if the assumption is wrong.
Code Example
class _MyWidgetState extends State<MyWidget> {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this); // set before any read
}
}Common Mistakes
- ×Using late to suppress a null-safety compiler error without verifying the initialization ordering actually holds.
- ×Using late for a value that's genuinely optional — it should be nullable (T?) instead.