CodeBlanks Logo Icon CodeBlanks

Type system

Learn the Dart type system and variance.

The type system

Dart's type system is static and sound: every expression has a type known at compile time. Object is the supertype of all objects, while dynamic defers checks to runtime.

Generic types (List<int>, Map<String, int>) let the same container work with different types. Variance rules (covariance, contravariance) govern subtype relationships of generic types.

Generic types

Generic types let a class or function work with different types. class Box<T> { final T value; Box(this.value); } allows usages like Box<int>, Box<String>.

The type parameter T is substituted with the actual type. Generics reduce code duplication and keep type safety: trying to extract a String from a Box<int> is a compile error.

Practice A generic Box class

Define a generic Box<T> class with final T value; field, Box(this.value); constructor and T unwrap() => value; method. In main create final box = Box<String>('Merhaba');; print the result with print(box.unwrap());.

Starter code

main.dart
void main() {
  // define a Box<T> generic class (value field; unwrap method)
  // create a Box<String>; print unwrap() result
}

Sample solution

main.dart
class Box<T> {
  final T value;
  Box(this.value);
  T unwrap() => value;
}

void main() {
  final box = Box<String>('Merhaba');
  print(box.unwrap());
}

Expected output

Merhaba

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Match the type system concepts

Term Meaning
Object Supertype of all
dynamic Runtime checking
List<int> Integer list
Map<String, int> Key-value mapping

2 What is the difference between dynamic and Object?

  • They are the same
  • dynamic only holds numbers
  • Object only holds class instances
  • dynamic defers all type checks to runtime Correct answer

Explanation: Object checks at compile time.

3 Generic Box declaration

Question
class Box<T> {
  final T value;
  Box(this.value);
}

void main() {
  final box = Box<____>(42);
  print(box.value);
}
Answer
class Box<T> {
  final T value;
  Box(this.value);
}

void main() {
  final box = Box<int>(42);
  print(box.value);
}

Explanation: Box<int> creates an integer box and value returns 42.

All lessons in Expert