Skip to main content
The late modifier in Dart is applied to variable declarations to alter the language’s sound null safety semantics by deferring initialization until runtime. It instructs the compiler to bypass static initialization requirements for instance and top-level variables. For local variables, Dart still performs flow analysis; however, late relaxes the strict requirement that a variable must be definitely assigned before use. The compiler will only issue a static error if a late local variable is definitely unassigned at the point of access. Otherwise, it defers the initialization check dynamically to the variable’s first access.

Syntax and Scope

The late modifier precedes the type declaration. It can be applied to top-level variables, instance fields, and local variables. It can be used with or without an immediate initializer and combined with the final modifier.

Core Mechanics

1. Runtime Initialization Checks

When a late variable is declared without an initializer, the Dart runtime tracks the variable’s initialization state. If the compiler cannot prove the variable is definitely unassigned, it allows the code to compile but inserts a runtime check. If the variable is read before a value is assigned, the runtime throws a LateInitializationError.

2. Lazy Evaluation

When a late variable is declared with an initializer, the evaluation of the initializer expression is deferred. The expression is not executed when the variable comes into scope or when an object is instantiated. It is executed exactly once, at the exact moment the variable is first read.

3. Interaction with Nullable Types

The late modifier can be applied to nullable types (e.g., Type?). This combination allows the runtime to distinguish between a variable that is truly uninitialized and a variable that has been explicitly initialized to null.

4. Interaction with final

The late modifier can be combined with final to create a variable that is both deferred and immutable after its initial assignment.
  • late final without initializer: The variable can be assigned exactly once at runtime. Any subsequent attempt to reassign it will result in a LateInitializationError.
  • late final with initializer: The initializer is evaluated lazily on first access, and the resulting value is permanently bound to the variable.

5. Instance Context Access in Initializers

Because late field initializers are evaluated lazily after instance construction is complete, they have access to the instance’s this context. A late field’s initializer can safely reference other instance methods, properties, or this itself, which is strictly prohibited for standard field initializers during object creation.
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More