Flutter & Dart Development
Variables & Type System
Theory & Concepts
Understanding Dart's Variable System
Dart is a strongly typed language with optional type annotations and powerful type inference. This gives you the best of both worlds: safety and conciseness.
đĄ Why This Matters: Proper variable usage prevents bugs, makes code self-documenting, and enables better IDE support with autocomplete and error checking.
Variable Declaration Options
Dart offers four main ways to declare variables:
1. var - Type Inferred
- Dart automatically determines the type from the initial value
- Type cannot change after assignment
- Use when type is obvious from context
2. final - Runtime Constant
- Value set once at runtime and cannot change
- Type can be inferred or explicit
- Similar to JavaScript's
const
3. const - Compile-Time Constant
- Value must be known at compile time
- Deeply immutable (all nested values are const too)
- More restrictive than
final
4. Explicit Type - Clear Declaration
- Specify the exact type
- Use when type isn't obvious or for API clarity
- Required for uninitialized variables
Type System Fundamentals
Built-in Types:
Numbers:
int- Integers (whole numbers):42,-100double- Floating-point:3.14,-0.5num- Supertype of both int and double
Text:
String- Text data:'Hello',"World"- Supports interpolation:
'Value: $variable' - Multi-line strings with triple quotes
Boolean:
bool- True or false values- Only
trueandfalse(no truthy/falsy)
Collections:
List- Ordered collection:[1, 2, 3]Set- Unique values:{1, 2, 3}Map- Key-value pairs:{'key': 'value'}
Dynamic vs Object
dynamic:
- Disables type checking
- Use sparingly (loses type safety)
- Type errors found at runtime
Object:
- Root of Dart's type hierarchy
- More type-safe than dynamic
- Requires explicit casting
â ī¸ Best Practice: Avoid dynamic when possible. Use specific types or generics instead.
Type Inference Rules
Dart's type inference is smart:
- From initialization:
var x = 5;âint - From function return:
var result = someFunction(); - Generic type inference:
var list = [1, 2];âList<int>
When to Use Each Declaration
Use var:
- Type is obvious:
var name = 'Alice'; - Local variables with clear initialization
Use final:
- Value won't change after initialization
- Can't be known at compile time:
final timestamp = DateTime.now(); - Function parameters that shouldn't change
Use const:
- Compile-time constants:
const pi = 3.14159; - Deeply immutable data structures
- Performance optimization (single instance)
Use explicit types:
- Public APIs and class fields
- Uninitialized variables:
int? count; - When type isn't obvious
Common Pitfalls
Mistake 1: Trying to Reassign final/const
final x = 10;x = 20; // â Error: Can't assign to final variableMistake 2: Using const for Runtime Values
const now = DateTime.now(); // â Error: Not a compile-time constantfinal now = DateTime.now(); // â
CorrectMistake 3: Overusing dynamic
dynamic data = getData(); // â Loses type safetyvar data = getData(); // â
Better: maintains typeSummary
Key Takeaways:
var= type inferred, can't reassign typefinal= set once at runtime, immutableconst= compile-time constant, deeply immutable- Use explicit types for clarity and uninitialized variables
- Avoid
dynamicwhen possible
Best Practices:
- Prefer
finalovervarwhen value won't change - Use
constfor compile-time constants - Be explicit with public API types
- Let type inference work for obvious cases
Remember: Strong typing catches bugs early and makes code self-documenting!
Lesson Content
Master Dart's variable declarations, type system, and type inference. Learn the differences between var, final, const, and explicit types.