Lesson 19 min

Type System & Inference

00:00 / 00:00

Dart's Sound Type System

Dart has a sound static type system. "Sound" means the type system makes guarantees the compiler can verify — if the type checker says something is a String, it is always a String at runtime. No exceptions, no surprises.

Soundness was achieved in Dart 2.0 (2018). Before that, Dart had optional typing — a design the team ultimately abandoned for stronger safety guarantees.

Built-In Primitive Types

dart
// Numbers int age = 25; // 64-bit integer double pi = 3.14159; // 64-bit floating point num flexible = 42; // supertype of int and double // Strings String name = 'JavaShark'; String multiLine = ''' This is multi-line '''; // Booleans bool isActive = true; // Collections (covered in depth later) List<int> scores = [95, 87, 92]; Map<String, int> grades = {'Alice': 95, 'Bob': 87}; Set<String> tags = {'dart', 'flutter'};

Type Inference with var and final

Dart infers types from the initializer — you don't always need to write the type:

dart
var name = 'JavaShark'; // inferred as String var count = 42; // inferred as int final ratio = 3.14; // inferred as double, cannot be reassigned // The type IS still checked — this is a compile error: // name = 123; // Error: A value of type 'int' can't be assigned to 'String'

dynamic vs Object? — The Escape Hatches

dart
// dynamic: opts OUT of type checking entirely dynamic anything = 'hello'; anything = 42; // OK anything.foo(); // No compile error, but may throw at runtime! // Object?: the safe alternative — accepts any non-null value Object? safe = 'hello'; safe = 42; // OK // safe.length; // Compile error! Must cast first if (safe is String) { print(safe.length); // Smart cast — safe inside is block }

Prefer Object? over dynamic. It forces you to check the type before using it, keeping the type system sound.

Generics

Dart supports full reified generics — the type information is available at runtime:

dart
class Repository<T> { final List<T> _items = []; void add(T item) => _items.add(item); T get(int index) => _items[index]; List<T> getAll() => List.unmodifiable(_items); } final userRepo = Repository<User>(); userRepo.add(User('Alice', 30)); print(userRepo is Repository<User>); // true — generics are reified!

Summary

Dart's type system gives you the safety of a statically typed language with the ergonomics of a dynamically typed one. Type inference reduces boilerplate without sacrificing safety. Avoid dynamic — let the type system work for you.

WhatsApp