In Dart, what does the => arrow syntax mean in a function or member declaration, and what can't you write after it?
answer
- shorthand for a single return
- expressions only, no statements
- conditional and switch expressions qualify
- braces after the arrow
- fine on void functions and setters
basics
~20 sIn Dart, => expr; is shorthand for { return expr; }. Only an expression may follow the arrow: a conditional or switch expression works, an if statement or loop does not, and => { ... } is a collection literal, not a block.
solid answer
~40 s`=> expr;` is exactly `{ return expr; }`, and it works for functions, methods, getters, setters, operators and anonymous functions, such as `void main() => runApp(const App());`. Only an expression may follow the arrow: `cond ? a : b`, a switch expression or a `throw` are fine, while an `if` statement or a loop is not. A common Flutter slip is `onTap: () => { save() }`; the braces are parsed as a set or map literal, not a block, so write `() => save()` or `() { save(); }`. On a `void` function the expression's value is simply discarded. Effective Dart suggests arrows for simple members and a block body once the expression gets long or nested.
code
dart · 22 linesclass Price {
Price(this.amount);
num amount;
bool get isFree => amount == 0; // getter
String get label => isFree ? 'Free' : '$amount EUR'; // conditional expression
set discount(num percent) => amount = amount * (100 - percent) / 100; // setter
}
String tier(num amount) => switch (amount) {
0 => 'free',
< 10 => 'cheap',
_ => 'regular',
};
void log(String message) => print(message); // value discarded
void main() {
final p = Price(20)..discount = 50;
log(p.label); // 10.0 EUR
log(tier(p.amount)); // regular
}go deeper
Recall that => expr; means { return expr; } and that only an expression may follow the arrow.
Explain which constructs count as expressions (conditional, switch expression, throw) and why => { } creates a collection literal.
Review for readability: spot arrow bodies that hide cascades or nested conditionals and ask for a block body with named locals.
Decide whether to adopt prefer_expression_function_bodies across the codebase, weighing brevity against readability of complex members.
## What `=>` means In a Dart function or member declaration, `=> expr;` is shorthand for a block body that returns that expression: `{ return expr; }`. It is often called **arrow syntax**. ```dart bool isFree(num price) => price == 0; // same as bool isFree(num price) { return price == 0; } ``` It works on top-level functions, methods, getters, setters, operators and function expressions (anonymous functions). A classic Flutter example is `void main() => runApp(const App());`. ## Only an expression may follow The part between `=>` and `;` must be an **expression**, something that evaluates to a value. Statements are not allowed: | After `=>` | Allowed? | |---|---| | `a > b ? a : b` (conditional expression) | yes | | `switch (x) { ... }` as a switch **expression** | yes | | `throw StateError('nope')` (throw is an expression) | yes | | `if (a > b) a` (if statement) | no | | `for (...) ...` (loop) | no | | `{ a; b; }` (a block) | no: the braces become a set or map literal | The last row is a real trap. Code written as `onTap: () => { save() }` does **not** run a block containing `save()`. The braces after `=>` are parsed as a **set or map literal**, so at best the function returns a collection built from that expression, and depending on the types the analyzer may reject it. Write `onTap: () => save()` or use a block body `onTap: () { save(); }`. ## Arrow on `void` functions An arrow body is fine on a `void` function: `void log(String m) => print(m);`. The expression is evaluated and its value is discarded because the declared return type is `void`. Setters work the same way: `set width(num v) => _width = v;`. ## When to use it, according to Effective Dart Effective Dart says to **consider `=>` for simple members** that compute and return a value, and warns against abusing it: - Good fits: getters like `double get area => width * height;`, one-line helpers, small setters paired with arrow getters. - Poor fits: anything longer than a couple of lines or with deeply nested expressions; cascades and chained conditionals are named as common offenders. Switch to a block body with statements and local variables. The `prefer_expression_function_bodies` lint (not in the default sets) suggests arrows where a block holds a single `return`. ## Summary of the mechanics 1. `=> e;` equals `{ return e; }`. 2. Only expressions may follow; conditional expressions, switch expressions and `throw` qualify, statements do not. 3. `=> { ... }` is a collection literal, not a block. 4. On a `void` function the value is discarded. 5. Prefer a block body once readability suffers. ## Arrow bodies in anonymous functions Arrow syntax is most common in **function expressions** passed as arguments: `prices.where((p) => p > 0)`, `items.map((i) => i.name)`. The same rule applies: one expression, implicitly returned. When a callback needs two statements, such as updating state and logging, use a block body `(p) { ... }` rather than squeezing both into one expression with a cascade or a comma-separated trick. Closures and tear-offs, and how they capture variables, are a separate topic. ## What an interviewer listens for - The exact equivalence with `{ return expr; }`. - The expression-only rule, with an example of a statement that fails. - The `=> { }` trap, which is common in Flutter callbacks. - Judgement about when an arrow stops helping readability.
- What does the Flutter callback onPressed: () => { save() } actually do?The braces after `=>` are parsed as a collection literal, not a block. Where it compiles at all, the closure evaluates `save()` as the element of a set literal and returns that set, instead of running a block of statements; depending on types the analyzer may reject it. Either way it signals a misunderstanding. Write `onPressed: () => save()`, a block body `() { save(); }`, or `onPressed: save` if the signature matches.
- Can you use => with an if/else in Dart?Not with an `if` statement, because only expressions may follow the arrow. Use a conditional expression, `=> isFree ? 'Free' : '$amount EUR';`, or, for several branches, a Dart 3 switch expression. When the logic needs statements or local variables, switch to a block body.
saying these in an interview costs you the question
- Thinks => can only be used on anonymous functions
- Puts an if statement after =>
- Writes () => { doWork() } expecting a block
- Believes arrow functions cannot return void
- Uses => for long nested expressions to save lines