๐ŸŽฏ Dart Cheat Sheet

Modern Dart with null safety โ€” types, async, streams, isolates and more.

๐Ÿ”
๐Ÿ“ฆ Variables & Types
Variable declarations
var name = 'Dart';        // type inferred
String city = 'Bangkok';  // explicit type
final pi = 3.14;          // runtime const (single-assign)
const maxAge = 150;       // compile-time const
late String lazyVal;      // initialized before use
Core types
int    age = 25;
double score = 9.5;
num    value = 42;        // int or double
String name = 'Feem';
bool   isActive = true;
dynamic anything = 'any type';
Object obj = 42;
Type conversion
int n    = int.parse('42');
double d = double.parse('3.14');
String s = 42.toString();
int? i   = int.tryParse('abc');  // returns null on fail

// Check type
if (value is String) { ... }
if (value is! int)   { ... }
String interpolation & multiline
final msg = 'Hello, $name!';
final calc = 'Result: ${2 + 2}';
final raw = r'No \n escaping here';
final multi = '''
  Multi
  line string
''';
๐Ÿ›ก๏ธ Null Safety
Nullable types
String? name;           // nullable
String name2 = 'Hi';   // non-nullable (never null)

name?.length            // null-aware access
name ?? 'default'       // null-coalescing
name ??= 'fallback';    // assign if null
name!.length            // assert non-null (throws if null)
Late initialization
late String description;

void init() {
  description = 'Set before use';
}

// Late with lazy init
late final expensiveValue = computeValue();
Null-aware operators
user?.address?.city     // chained null-aware
list?[0]                // null-aware index
func?.call()            // null-aware function call

// Cascade with null check
builder?..setName('Feem')..build();
๐Ÿ“š Collections
List
final list = [1, 2, 3];
final typed = <String>['a', 'b'];
final fixed = List.filled(3, 0);         // [0, 0, 0]
final generated = List.generate(5, (i) => i * 2);

list.add(4);
list.addAll([5, 6]);
list.remove(1);
list.removeAt(0);
list.contains(3);        // true
list.indexOf(2);         // 1
list.length;
list.isEmpty;
list.first; list.last;
list.reversed.toList();
list.sublist(1, 3);      // [2, 3]

// Functional
list.map((e) => e * 2).toList();
list.where((e) => e > 2).toList();
list.reduce((a, b) => a + b);
list.fold(0, (acc, e) => acc + e);
list.any((e) => e > 2);
list.every((e) => e > 0);
list.sort((a, b) => a.compareTo(b));
Map
final map = {'name': 'Feem', 'age': 30};
map['city'] = 'Bangkok';           // add/update
map.remove('age');
map.containsKey('name');           // true
map.containsValue('Feem');         // true
map.keys.toList();
map.values.toList();
map.entries.map((e) => '${e.key}=${e.value}');

// From lists
Map.fromIterables(keys, values);
{for (var item in list) item.id: item};   // map literal loop
Set & spread
final set = {1, 2, 3};         // Set<int>
set.add(4);
set.contains(2);               // true
set.union({3, 4, 5});
set.intersection({2, 3, 10});

// Spread operator
final a = [1, 2];
final b = [0, ...a, 3];       // [0, 1, 2, 3]
final c = [...?nullableList];  // null-safe spread

// Collection if/for
final items = [
  'always',
  if (isLoggedIn) 'profile',
  for (var i in range) 'item_$i',
];
๐Ÿ”ง Functions
Function syntax
// Regular function
int add(int a, int b) => a + b;

// Named params (optional with default)
void greet({required String name, int age = 0}) {}

// Positional optional params
String format(String s, [String? prefix]) {}

// Higher-order function
List<T> mapList<T>(List items, T Function(dynamic) fn) =>
  items.map(fn).toList();
Arrow functions & closures
// Arrow function
int square(int x) => x * x;

// Anonymous function (closure)
final multiply = (int a, int b) => a * b;

// Typedef
typedef Predicate<T> = bool Function(T value);

Predicate<int> isEven = (n) => n % 2 == 0;
Cascade operator
final result = StringBuffer()
  ..write('Hello')
  ..write(' ')
  ..write('World');

print(result.toString()); // Hello World
๐Ÿ—๏ธ OOP
Class basics
class User {
  final String name;
  int age;

  // Generative constructor
  User({required this.name, required this.age});

  // Named constructor
  User.guest() : name = 'Guest', age = 0;

  // Factory constructor
  factory User.fromJson(Map<String, dynamic> json) =>
    User(name: json['name'], age: json['age']);

  // Getter / setter
  bool get isAdult => age >= 18;
  set displayAge(int value) => age = value;

  // Override
  @override
  String toString() => 'User($name, $age)';
}
Inheritance & mixins
class Animal {
  void breathe() => print('breathing');
}

mixin CanFly {
  void fly() => print('flying');
}

class Bird extends Animal with CanFly {
  @override
  void breathe() {
    super.breathe();
    print('bird breathing');
  }
}

// Abstract class
abstract class Repository {
  Future<List<User>> getAll();
  Future<void> save(User user);
}
Sealed & enum (Dart 3)
// Sealed class
sealed class Result<T> {}
class Success<T> extends Result<T> { final T data; Success(this.data); }
class Failure<T> extends Result<T> { final String msg; Failure(this.msg); }

// Switch exhaustive pattern
switch (result) {
  case Success(:final data) => print(data),
  case Failure(:final msg)  => print(msg),
}

// Enhanced enum
enum Status {
  loading, success, error;
  bool get isLoading => this == Status.loading;
}
๐Ÿ”ฃ Generics
Generic classes & functions
class Box<T> {
  final T value;
  Box(this.value);
  T get() => value;
}

T firstOrDefault<T>(List<T> list, T defaultVal) =>
  list.isEmpty ? defaultVal : list.first;

// Bounded generics
class NumBox<T extends num> {
  final T value;
  NumBox(this.value);
  T doubled() => (value * 2) as T;
}
โณ Async / Await
Future basics
Future<String> fetchUser() async {
  await Future.delayed(const Duration(seconds: 1));
  return 'Feem';
}

// Call it
final name = await fetchUser();

// Future.value / error
Future.value('immediate');
Future.error(Exception('oops'));
Error handling
try {
  final data = await fetchUser();
  print(data);
} on NetworkException catch (e) {
  print('Network error: $e');
} catch (e, stackTrace) {
  print('Error: $e\n$stackTrace');
} finally {
  print('Always runs');
}
Parallel execution
// Wait for all
final results = await Future.wait([
  fetchUser(),
  fetchPosts(),
]);

// Wait for any
final first = await Future.any([
  slowFuture(),
  fastFuture(),
]);

// With timeout
await fetchUser().timeout(
  const Duration(seconds: 5),
  onTimeout: () => 'timeout fallback',
);
๐ŸŒŠ Streams
Create & listen to streams
// Stream from iterable
final s = Stream.fromIterable([1, 2, 3]);

// Periodic stream
final ticker = Stream.periodic(
  const Duration(seconds: 1),
  (i) => i,
);

// StreamController (single-subscription)
final ctrl = StreamController<int>();
ctrl.stream.listen(
  (data) => print(data),
  onError: (e)  => print(e),
  onDone:  ()   => print('done'),
);
ctrl.add(1);
ctrl.close();

// Broadcast (multi-subscriber)
final broad = StreamController<int>.broadcast();
Async generator
Stream<int> countUp(int max) async* {
  for (int i = 0; i <= max; i++) {
    await Future.delayed(const Duration(milliseconds: 100));
    yield i;
  }
}

await for (final n in countUp(5)) {
  print(n);    // 0, 1, 2, 3, 4, 5
}
Stream operators
stream
  .where((e) => e % 2 == 0)      // filter
  .map((e) => e * 10)            // transform
  .take(5)                        // first 5 items
  .distinct()                     // skip duplicates
  .timeout(Duration(seconds: 5))  // timeout
  .listen(print);
๐Ÿ”Œ Extensions
Extension methods
extension StringX on String {
  bool get isEmail => contains('@');
  String capitalize() => '${this[0].toUpperCase()}${substring(1)}';
  String get reversed => split('').reversed.join();
}

extension ListX<T> on List<T> {
  T? get firstOrNull => isEmpty ? null : first;
  List<T> takeLast(int n) => sublist(length - n);
}

// Usage
'hello'.capitalize()     // 'Hello'
'test@mail.com'.isEmail  // true
[1,2,3].firstOrNull      // 1
๐ŸŽจ Patterns (Dart 3)
Pattern matching
// Object pattern
switch (user) {
  case User(name: 'Feem', age: var a) when a >= 18:
    print('Adult Feem');
  case User(:final name):
    print('User: $name');
}

// Destructuring
final (x, y) = (10, 20);       // record destructure
final [first, ...rest] = list; // list destructure
final {'name': name} = map;    // map destructure

// Guards (when clause)
final value = switch (score) {
  >= 90 => 'A',
  >= 80 => 'B',
  >= 70 => 'C',
  _ => 'F',
};
Records (Dart 3)
// Record type
(String, int) user = ('Feem', 30);
final (name, age) = user;

// Named record fields
({String name, int age}) person = (name: 'Feem', age: 30);
print(person.name);    // Feem

// Return multiple values
(int, String) getInfo() => (42, 'hello');
๐Ÿงต Isolates
Isolate.run (Dart 2.19+)
// Run heavy computation in separate isolate
final result = await Isolate.run(() {
  // Heavy work โ€” doesn't block UI
  return computeExpensiveValue();
});
Compute (Flutter convenience)
import 'package:flutter/foundation.dart';

// Top-level or static function required
List<Item> parseItems(String json) {
  // heavy parsing...
}

final items = await compute(parseItems, rawJson);