Coding · Programming languages
Dart tutorial for beginners
Short answer
Dart is a statically typed, object-oriented language from Google, best known as the language of the Flutter app framework. It has sound null safety, compiles to native code and to JavaScript or WebAssembly, and supports fast hot reload during development. This page walks through setup, types, null safety, control flow, functions, collections, classes, async code and error handling.
What Dart is and what it is used for
Dart is a client-optimized programming language developed by Google. It is statically typed with type inference, has sound null safety, and compiles both to native machine code (for mobile, desktop and servers) and to JavaScript or WebAssembly (for the web). During development it runs on a virtual machine with hot reload, so changes appear in a running app within seconds.
Most people learn Dart to build apps with Flutter, Google's UI toolkit for Android, iOS, web, Windows, macOS and Linux from one codebase. Dart is also used for command-line tools and backend services.
Install Dart and run Hello, world
Install the Dart SDK from dart.dev (or install Flutter, which bundles Dart). Every Dart program starts at a top-level main function.
// hello.dart
void main() {
print('Hello, world!');
}dart run hello.dart
# Hello, world!
dart compile exe hello.dart # builds a native executable
dart create my_app # creates a new console projectYou can also try every example on this page in DartPad, the browser-based editor at dartpad.dev.
Variables and basic types
Use var to let the compiler infer the type, final for a variable that is assigned once, and const for a compile-time constant. You can always write the type explicitly instead.
void main() {
var name = 'Dart'; // inferred as String
int year = 2011; // explicit type
final now = DateTime.now(); // set once, at run time
const pi = 3.14159; // compile-time constant
double ratio = 2; // int literal becomes 2.0
bool ok = year > 2000;
print('$name since $year, pi=${pi.toStringAsFixed(2)}, ok=$ok, ratio=$ratio');
// Dart since 2011, pi=3.14, ok=true, ratio=2.0
print(now.year > 2000); // true
}| Type | Example | Notes |
|---|---|---|
int | 42 | integer; 64-bit on native platforms |
double | 3.14 | 64-bit floating point |
num | 7 or 7.5 | supertype of int and double |
bool | true | only true and false are allowed in conditions |
String | 'hi' | UTF-16; supports $x and ${expr} interpolation |
dynamic | anything | turns off static checking; avoid in most code |
On the web, int values are represented as JavaScript numbers, so very large integers can lose precision there.
Sound null safety
Since Dart 3, all Dart code uses sound null safety. A variable of type String can never be null; to allow null, write String?. The compiler checks every use, so null errors are caught before the program runs.
int lengthOf(String? s) {
// return s.length; // compile error: s might be null
if (s == null) return 0;
return s.length; // promoted to String after the check
}
void main() {
String? nickname;
print(nickname?.length); // null (null-aware access)
print(nickname ?? 'guest'); // guest (default if null)
nickname ??= 'dee'; // assign only if null
print(lengthOf(nickname)); // 3
late String config; // initialized later, checked at run time
config = 'loaded';
print(config); // loaded
}Control flow
Dart has the usual if, for, while and do-while, plus a for-in loop over any iterable. Since Dart 3, switch supports pattern matching and can be used as an expression.
void main() {
var scores = [72, 95, 48];
for (var s in scores) {
if (s >= 90) {
print('$s excellent');
} else if (s >= 50) {
print('$s pass');
} else {
print('$s fail');
}
}
for (var i = 0; i < 3; i++) {
print('i = $i');
}
var day = 6;
var kind = switch (day) {
6 || 7 => 'weekend',
>= 1 && <= 5 => 'weekday',
_ => 'invalid',
};
print(kind); // weekend
}Functions
Functions are first-class objects. Parameters can be positional, optional positional in [], or named in {}. Named parameters are optional unless marked required. The arrow syntax => is shorthand for a function that returns one expression.
int add(int a, int b) => a + b;
String greet(String name, {String greeting = 'Hello', required bool loud}) {
var text = '$greeting, $name';
return loud ? text.toUpperCase() : text;
}
String label(String text, [int? width]) =>
width == null ? text : text.padRight(width, '.');
void main() {
print(add(2, 3)); // 5
print(greet('Ana', loud: false)); // Hello, Ana
print(greet('Ana', greeting: 'Hi', loud: true)); // HI, ANA
print(label('id', 5)); // id...
var twice = (int x) => x * 2; // anonymous function
print([1, 2, 3].map(twice).toList()); // [2, 4, 6]
}Collections: List, Set, Map and records
The core collections are List (ordered), Set (unique items) and Map (key-value pairs). Collection literals support if, for and the spread operator .... Records, added in Dart 3, group several values without declaring a class.
void main() {
var nums = [3, 1, 2]; // List<int>
nums.add(4);
nums.sort();
print(nums); // [1, 2, 3, 4]
var tags = {'dart', 'flutter', 'dart'};
print(tags.length); // 2
var ages = {'Ann': 31, 'Bo': 25}; // Map<String, int>
ages['Cy'] = 40;
print(ages['Bo']); // 25
var showAll = false;
var menu = ['Home', if (showAll) 'Admin', for (var n in nums) 'Item $n'];
print(menu); // [Home, Item 1, Item 2, Item 3, Item 4]
(String, int) pair = ('Ann', 31); // a record
var (who, age) = pair; // destructuring
print('$who is $age'); // Ann is 31
}Classes and async/await
Dart is object-oriented: every value is an object. Classes support constructors with initializing formals (this.x), named constructors, getters, mixins and interfaces. Asynchronous code uses Future and Stream with async and await, which keeps Flutter apps responsive while waiting for files or the network.
class Point {
final double x, y;
const Point(this.x, this.y);
Point.origin() : x = 0, y = 0; // named constructor
double get sum => x + y; // getter
@override
String toString() => 'Point($x, $y)';
}
Future<String> fetchUser() async {
await Future.delayed(Duration(milliseconds: 100));
return 'ana';
}
Future<void> main() async {
print(Point(1, 2).sum); // 3.0
print(Point.origin()); // Point(0.0, 0.0)
var user = await fetchUser();
print('user: $user'); // user: ana
}Error handling
Throw an exception with throw and handle it with try, on, catch and finally. Use on SomeType to catch a specific type. Dart distinguishes Exception (an expected problem the program can handle) from Error (a bug, such as a failed assertion or a range error) that you normally should not catch.
int parseAge(String s) {
var n = int.tryParse(s); // null instead of throwing
if (n == null || n < 0) {
throw FormatException('Not a valid age: $s');
}
return n;
}
void main() {
for (var input in ['42', 'abc']) {
try {
print(parseAge(input));
} on FormatException catch (e) {
print('Error: ${e.message}');
} finally {
print('checked $input');
}
}
}
// 42 / checked 42 / Error: Not a valid age: abc / checked abcA small complete program: shopping cart total
This program models products with a class, stores a cart in a map and prints a receipt. It combines classes, maps, string formatting and collection methods.
class Product {
final String name;
final double price;
const Product(this.name, this.price);
}
void main() {
const apple = Product('Apple', 0.5);
const bread = Product('Bread', 2.25);
final cart = <Product, int>{apple: 6, bread: 2};
var total = 0.0;
cart.forEach((product, qty) {
final line = product.price * qty;
total += line;
print('${product.name.padRight(6)} x$qty ${line.toStringAsFixed(2)}');
});
final count = cart.values.reduce((a, b) => a + b);
print('$count items, total ${total.toStringAsFixed(2)}');
}
// Apple x6 3.00
// Bread x2 4.50
// 8 items, total 7.50Where to go next
- The Dart language tour and tutorials at dart.dev.
- Effective Dart, the official style and design guide.
- The Flutter documentation at flutter.dev if you want to build apps.
- pub.dev, the package repository for Dart and Flutter.
FAQ
Is Dart only for Flutter?
No. Dart is a general-purpose language and can build command-line tools, servers and web apps. Flutter is simply the most popular reason to learn it.
Is Dart compiled or interpreted?
Both modes exist. During development Dart runs on a VM with just-in-time compilation and hot reload; for release it is compiled ahead of time to native machine code, or to JavaScript or WebAssembly for the web.
What is the difference between final and const in Dart?
A final variable is assigned once, possibly at run time. A const value must be known at compile time and is deeply immutable, which lets Flutter reuse constant widgets.
Is Dart similar to Java or JavaScript?
Its C-style syntax and classes feel familiar to Java, C# and JavaScript developers. Unlike JavaScript, Dart is statically typed and has sound null safety.
What does the ?? operator do in Dart?
a ?? b returns a if it is not null and otherwise b. The related a ??= b assigns b to a only when a is null.