Dart Basics Cheatsheet
Cheatsheet · 28 Sep 2026
AI-generated Written with AI, solely for personal reference.
Dart is the language behind Flutter: typed, null-safe and compiled. Snippets without a main go inside void main() { ... }.
Run Dart
dart --version
dart run hello.dart # run a file
dart create my_app # new console project
dart format . # format code
dart analyze # check for problems
void main() {
print('Hello, world!');
}
Variables
var name = 'Maxine'; // type inferred (String)
int age = 30; // explicit type
double height = 1.75;
bool isActive = true;
final city = 'Springfield'; // set once, at runtime
const pi = 3.14159; // fixed at compile time
age += 1;
print('$name is $age'); // Maxine is 31
print('Next year: ${age + 1}'); // Next year: 32
print(height.runtimeType); // double
print('$isActive $city $pi');
| Keyword | Can change? | When is it set? |
|---|---|---|
var / a type |
Yes | Any time |
final |
No | Once, at runtime |
const |
No | At compile time |
late |
Set once, later | Before first use |
Null safety
Types can’t hold null unless you add ?.
String? findNickname(String name) => name == 'Maxine' ? 'Max' : null;
void main() {
String? nickname = findNickname('Ali'); // String? : may be null (it is here)
print(nickname ?? 'no nickname'); // ?? : fallback if null
print(nickname?.length); // ?. : null instead of an error
nickname ??= 'Max'; // assign only if null
print(nickname.length); // 3: Dart knows it's not null now
String sure = findNickname('Maxine')!; // ! : "I promise it's not null" (throws if wrong)
print(sure); // Max
}
Strings and numbers
var s = 'hello world';
print(s.toUpperCase()); // HELLO WORLD
print(s.split(' ')); // [hello, world]
print(s.contains('world')); // true
print(s.substring(0, 5)); // hello
print('ab' * 3); // ababab
var multi = '''
Line one
Line two''';
print(multi);
print(7 ~/ 2); // 3 integer division
print(7 / 2); // 3.5
print(7 % 2); // 1
print(int.parse('42') + 1); // 43
print(3.14159.toStringAsFixed(2)); // 3.14
print(42.toString().length); // 2
Collections
// List: ordered
var fruits = ['apple', 'banana'];
fruits.add('cherry');
fruits.remove('banana');
print(fruits); // [apple, cherry]
print(fruits.length); // 2
print(fruits.first); // apple
// Set: unique items
var tags = {'dart', 'flutter'};
tags.add('dart'); // already there, so nothing changes
print(tags); // {dart, flutter}
// Map: key -> value
var ages = {'Ali': 30, 'Siti': 25};
ages['Aisha'] = 28;
print(ages['Ali']); // 30
print(ages.containsKey('Bob')); // false
ages.forEach((name, age) => print('$name: $age'));
// Spread, collection if and for
var more = [...fruits, 'date'];
var showExtra = true;
var menu = ['home', if (showExtra) 'extra', for (var f in fruits) f.toUpperCase()];
print(more); // [apple, cherry, date]
print(menu); // [home, extra, APPLE, CHERRY]
// Handy methods
var nums = [3, 1, 4, 1, 5];
print(nums.map((n) => n * 2).toList()); // [6, 2, 8, 2, 10]
print(nums.where((n) => n > 2).toList()); // [3, 4, 5]
print(nums.reduce((a, b) => a + b)); // 14
Control flow
var score = 72;
if (score >= 80) {
print('A');
} else if (score >= 60) {
print('B');
} else {
print('C');
}
var label = score >= 60 ? 'pass' : 'fail';
print(label); // pass
for (var i = 0; i < 3; i++) {
print(i); // 0 1 2
}
for (var fruit in ['apple', 'kiwi']) {
print(fruit);
}
var n = 3;
while (n > 0) {
n--;
}
// switch expression (Dart 3)
var day = 2;
var name = switch (day) {
1 => 'Mon',
2 => 'Tue',
_ => 'Other',
};
print(name); // Tue
Functions
int add(int a, int b) => a + b; // => for one-expression bodies
// Named parameters in {}; required, or with a default
String greet({required String name, String greeting = 'Hello'}) {
return '$greeting, $name!';
}
// Optional positional parameters in []
String describe(String item, [String? colour]) =>
colour == null ? item : '$colour $item';
void main() {
print(add(2, 3)); // 5
print(greet(name: 'Maxine')); // Hello, Maxine!
print(greet(name: 'Maxine', greeting: 'Hi')); // Hi, Maxine!
print(describe('car')); // car
print(describe('car', 'red')); // red car
// Functions are values
var square = (int x) => x * x;
print([1, 2, 3].map(square).toList()); // [1, 4, 9]
}
Classes
class BankAccount {
final String owner;
double _balance; // _ makes it private to the file
BankAccount(this.owner, [this._balance = 0]); // this.x assigns fields
BankAccount.empty(String owner) : this(owner); // named constructor
double get balance => _balance; // getter
void deposit(double amount) {
if (amount <= 0) throw ArgumentError('amount must be positive');
_balance += amount;
}
@override
String toString() => 'BankAccount($owner, $_balance)';
}
void main() {
var account = BankAccount('Maxine', 100);
account.deposit(50);
print(account.balance); // 150.0
print(account); // BankAccount(Maxine, 150.0)
print(BankAccount.empty('Siti')); // BankAccount(Siti, 0.0)
}
Inheritance, interfaces and mixins
abstract class Animal { // can't be created directly
final String name;
Animal(this.name);
String speak(); // subclasses must implement
String introduce() => '$name says ${speak()}';
}
class Dog extends Animal {
Dog(super.name); // pass name to the parent
@override
String speak() => 'Woof';
}
mixin Swimmer { // reusable behaviour
String swim() => 'swimming';
}
class Duck extends Animal with Swimmer {
Duck(super.name);
@override
String speak() => 'Quack';
}
abstract interface class Printable { // a contract, no code
String printLabel();
}
class Invoice implements Printable {
@override
String printLabel() => 'Invoice #1';
}
void main() {
print(Dog('Rex').introduce()); // Rex says Woof
var duck = Duck('Don');
print('${duck.introduce()}, ${duck.swim()}'); // Don says Quack, swimming
print(Invoice().printLabel()); // Invoice #1
}
Enums, records and patterns
enum Status {
active('Active'),
paused('Paused');
final String label;
const Status(this.label);
}
// A record bundles several values without a class
(String, int) nameAndAge() => ('Maxine', 30);
void main() {
var s = Status.paused;
print(s.label); // Paused
print(Status.values.length); // 2
var (name, age) = nameAndAge(); // destructure a record
print('$name $age'); // Maxine 30
var point = (x: 3, y: 4); // named record fields
print(point.x + point.y); // 7
Object value = [1, 2];
var text = switch (value) {
int n when n > 10 => 'big number',
int _ => 'number',
[var a, var b] => 'pair of $a and $b',
_ => 'something else',
};
print(text); // pair of 1 and 2
}
Errors
void main() {
try {
int.parse('abc');
} on FormatException catch (e) {
print('Bad number: ${e.message}'); // Bad number: Invalid radix-10 number
} finally {
print('done');
}
}
throw raises any object, usually an Exception or Error subclass such as ArgumentError or StateError.
Async code
A Future is a value that arrives later; await waits for it inside an async function.
Future<String> fetchUser() async {
await Future.delayed(Duration(milliseconds: 100)); // pretend network call
return 'Maxine';
}
Stream<int> countdown(int from) async* {
for (var i = from; i > 0; i--) {
yield i; // emit values one at a time
}
}
Future<void> main() async {
print('loading...');
var user = await fetchUser();
print('Hello, $user'); // Hello, Maxine
var results = await Future.wait([fetchUser(), fetchUser()]); // run in parallel
print(results); // [Maxine, Maxine]
await for (var n in countdown(3)) {
print(n); // 3 2 1
}
}