Variables and Types in Dart
Learn about variables, data types, type inference, and type conversions in Dart with practical Docker-ready examples
Dart is a statically, strongly typed language with sound null safety — every variable has a type known at compile time, and the compiler guarantees that a non-nullable variable can never hold null. This combination of static typing and null safety catches entire categories of bugs before your code ever runs.
Despite being statically typed, Dart keeps things concise. The var keyword lets the compiler infer the type from the assigned value, giving you the safety of static typing with the brevity of a dynamic language. Dart 3 added records and pattern matching that make working with structured data even more expressive.
In this tutorial you’ll learn Dart’s built-in types, how to declare and assign variables with var, explicit types, and final/const, how null safety works in practice, and how to perform type conversions and type checking.
The Complete Example
Create a file named variables.dart:
| |
Walkthrough
Primitive Types
Dart has a focused set of built-in types. Unlike C# or Java, there are no short, long, float, or byte — Dart keeps it simple.
| Type | Description | Examples |
|---|---|---|
int | Integer (arbitrary precision on VM, 64-bit on web) | 42, -7, 0xFF |
double | 64-bit IEEE 754 floating point | 3.14, -0.5, 1.0e10 |
num | Supertype of int and double | Either integer or float |
bool | Boolean | true, false |
String | UTF-16 string (immutable) | 'hello', "world" |
All types in Dart are objects — even int and bool inherit from Object. There are no “primitive” types in the Java sense; everything is an object with methods (42.toString(), 3.14.ceil()).
Type Inference with var
The var keyword lets the compiler deduce the type from the right-hand side. The variable is still statically typed — you cannot later assign a value of a different type.
| |
Use dynamic if you truly need a variable that can hold any type (rarely needed):
| |
final vs const
Both prevent reassignment, but they differ in when the value is determined:
final— set once at runtime. Use for values computed at runtime (API responses, timestamps, constructor parameters).const— compile-time constant. The value must be fully deterministic at compile time.
| |
Null Safety
Dart’s sound null safety means the compiler tracks nullability through your entire program. If a variable’s type doesn’t end with ?, it can never be null — the compiler enforces this statically.
Key null-aware operators:
| Operator | Meaning | Example |
|---|---|---|
?. | Null-aware access | name?.length → null if name is null |
?? | Null-coalescing | name ?? 'default' → fallback if null |
??= | Null-aware assignment | name ??= 'default' → assign only if null |
! | Null assertion | name!.length → throws if null |
Type Conversions
Dart does not perform implicit numeric conversions. You cannot assign an int to a double variable directly — you must call .toDouble(). This is stricter than most languages but prevents subtle precision bugs.
For string parsing, prefer tryParse over parse when handling user input — parse throws a FormatException on invalid input, while tryParse returns null.
Running with Docker
| |
Expected Output
── Primitive Types ──
int: 30
int: 8100000000
double: 3.14159265358979
double: -40.5
bool: true
String: Dart Developer
String: Hello
── Type Inference with var ──
count is int: 42
message is String: Hello, Dart!
ratio is double: 3.14
flag is bool: true
numbers is List<int> with 5 elements
── final and const ──
final appName: CodeArchaeology
final now: 2026-03-16
const piConst: 3.14159265358979
const daysInWeek: 7
const maxRetries: 3
Circumference of r=5 circle: 31.4159
── Null Safety ──
nullableName is null: true
optionalAge is null: true
nullableName after assignment: Alice
nullableName length: 5
maybeName?.length: null
maybeName ?? "default": default
── Type Conversions ──
int → double: 100 → 100.0
double → int (truncates): 3.99 → 3
String parsing:
int.parse("42") = 42
double.parse("3.14") = 3.14
bool.parse("true") = true
int.tryParse("123abc") = null
int.tryParse("999") = 999
Type checking:
42 is int: true
42 is double: false
42 is num: true
String representations of 255:
Decimal: 255
Hex: FF
Binary: 11111111
Key Concepts
- Static, strong typing with inference — every variable has a fixed type, but
varlets the compiler infer it from the initializer, keeping code concise without sacrificing safety. - Everything is an object — unlike Java or C#, Dart has no primitive types; even
intandboolare objects with methods, inheriting fromObject. - Sound null safety — the compiler guarantees that non-nullable variables can never hold
nullat runtime; use?to opt in to nullability, and null-aware operators (?.,??,!) to work with nullable types. finalvsconst— both prevent reassignment, butfinalis set once at runtime whileconstrequires a compile-time constant value; usefinalby default,constwhen the value is truly fixed.- No implicit numeric conversions — Dart does not automatically convert between
intanddouble; use explicit methods like.toDouble()and.toInt()to convert between numeric types. tryParseoverparse—int.parsethrows on invalid input;int.tryParsereturnsnulland is safer for user-supplied strings.numas a supertype — when a function should accept both integers and floating-point values, usenumas the parameter type.- String interpolation — use
$variablefor simple values and${expression}for complex expressions inside strings, avoiding manual concatenation.
Comments
Loading comments...
Leave a Comment