๐ฏ 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 loopSet & 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);