Skip to main content
A variable in Dart is a named reference to a memory location that stores an object. Because Dart is a purely object-oriented language, every variable holds a reference to an instance of a class, including fundamental types like numbers and booleans.

Declaration and Typing

Dart is a statically typed language that supports both explicit type annotations and static type inference. Explicit Typing You can explicitly declare the static type of a variable. The compiler enforces this type strictly.
String explicitString = 'Dart';
int explicitInteger = 42;
Type Inference (var) Using the var keyword allows the Dart analyzer to infer the variable’s static type at compile time based on its initializer. Once inferred, the type cannot change. However, if a var is declared without an initializer, Dart infers its static type as dynamic. This allows the variable to accept values of any type later in its lifecycle.
var inferredString = 'Dart'; // Statically inferred as String
// inferredString = 42;      // Compilation error

var uninitialized;           // Statically inferred as dynamic
uninitialized = 'Dart';      // Valid
uninitialized = 42;          // Valid
Dynamic Typing (dynamic) The dynamic keyword explicitly disables static type checking for a variable. The Dart analyzer defers type evaluation to runtime, allowing the variable to reference objects of different types over its lifecycle.
dynamic flexibleVariable = 'Dart';
flexibleVariable = 42; // Valid at runtime

Null Safety

Dart enforces sound null safety. By default, variables are non-nullable and must be initialized before they are read. Nullable Types (?) To allow a variable to hold a null reference, append a question mark (?) to the type declaration.
String? nullableString; // Defaults to null
Late Initialization (late) The late keyword instructs the compiler to defer definite assignment checks. It tells the compiler to trust the developer’s promise to initialize the variable before it is read. If the variable is accessed before initialization, Dart throws a LateInitializationError at runtime. While typically used with non-nullable types, late can also be applied to nullable variables to enforce explicit initialization before the variable is read, or to enable lazy initialization for a nullable type. Additionally, late enables lazy initialization. When a late variable is declared with an initializer, the expression is not evaluated until the variable is accessed for the first time.
late String deferredString;
deferredString = 'Initialized prior to read'; // Throws LateInitializationError if read before assignment

late String? lazyNullable; // Valid on nullable types

// Lazy initialization: the anonymous function executes only upon the first read of lazyData
late String lazyData = (() => 'Heavy Data')(); 

Immutability Modifiers

Dart provides two keywords to prevent variable reassignment: final and const. final A final variable can be assigned exactly once. Its value does not need to be known at compile time; it can be evaluated at runtime, though it can also be initialized with a compile-time constant. It can be used with explicit types or type inference.
final String runtimeConstant = DateTime.now().toString(); // Evaluated at runtime
final inferredFinal = 100; // Inferred as final int
const A const variable is a compile-time constant. It must be initialized with a value that is strictly known at compile time. Objects assigned to const variables are deeply, transitively immutable.
const double pi = 3.14159;
const inferredConst = 'Locked at compile time'; // Inferred as const String
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More