Dart Basics
Irbisa · cheatsheetSeptember 13, 2026

Dart Basics

Variables, types, functions, null safety, and core Dart syntax

Junior Developer20 itemscompressed for a skim
  1. 01

    What is null safety in Dart and what are nullable vs non-nullable types?

    Easy

    Null safety means a variable cannot hold null unless its type is marked nullable with a trailing question mark.

    // Non-nullable — must be initialized
    String name = 'Alice';
    
    // Nullable
    String? email;
    print(email?.length); // null (safe access)
    …
  2. 02

    What are the main data types in Dart?

    Easy

    Dart's core types cover numbers, text, booleans, three collections and a few special types like Never.

    int age = 30;
    double salary = 75000.50;
    num anything = 3; // can be int or double
    
    String name = 'Flutter';
    String interpolated = 'Hello, $name! Age: ${age + 1}';
    …
  3. 03

    Explain the difference between final and const in Dart.

    Easy

    Both final and const block reassignment; the difference is WHEN the value is fixed — final at runtime, const at compile time.

    // final — runtime value OK
    final name = 'Alice';
    final now = DateTime.now(); // ✅ runtime value
    
    // const — compile-time only
    const pi = 3.14159;
    …
  4. 04

    What are arrow functions, anonymous functions, and closures in Dart?

    Medium

    Functions in Dart are first-class objects — you can store them in variables, pass them as arguments and return them.

    // Named function
    int add(int a, int b) => a + b;
    
    // Arrow — single expression only
    double circle(double r) => 3.14159 * r * r;
    …
  5. 05

    Explain Dart collections: List, Map, Set and their common operations.

    Medium

    Dart ships three core collections: List for ordered items, Map for key-value pairs, and Set for unique values.

    // ── LIST ──────────────────────────────────────────
    var fruits = <String>['apple', 'banana', 'cherry'];
    fruits.add('date');
    fruits.remove('banana');
    fruits.sort();
    …
  6. 06

    What are Dart enums and how do enhanced enums work?

    Medium

    Dart has plain enums, which are a named set of constants, and enhanced enums, which add fields, methods and constructors.

    // Simple enum
    enum Status { pending, active, suspended, deleted }
    
    // Using simple enum
    Status userStatus = Status.active;
    print(userStatus.name);  // 'active'
    …
  7. 07

    Explain the cascade operator (..) and spread operator (...) in Dart.

    Medium

    The cascade operator chains several calls on one object and returns the object itself, while spread unpacks one collection into another.

    // ── Cascade operator (..) ──────────────────
    var paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;
    …
  8. 08

    When would you choose a Set over a List, or a Map over either?

    Easy

    Pick by the access pattern: List when order and index matter, Set when you need uniqueness and fast membership tests, Map when you look values up by key.

    // ── List ──────────────────────────────────
    var numbers = [1, 2, 3, 2]; // allows duplicates
    numbers.add(4);
    print(numbers[0]); // 1
    print(numbers.length); // 5
    …
  9. 09

    What are typedef and function types in Dart?

    Medium

    typedef declares a type alias, most often a name for a function signature you use in more than one place.

    // ── Function types ─────────────────────────
    // Function as variable
    int add(int a, int b) => a + b;
    var operation = add;
    print(operation(2, 3)); // 5
    …
  10. 10

    How do named and optional parameters work in Dart?

    Easy

    Dart parameters are positional and required by default; optional ones are either named, in braces, or positional, in brackets.

    // ── Named parameters ──────────────────────
    void greet({String name = 'Guest', int age = 0}) {
      print('Hello $name, age $age');
    }
    
    greet();                        // Hello Guest, age 0
    …
  11. 11

    What is the difference between var, dynamic, and Object? in Dart?

    Easy

    Of the three, only dynamic actually switches type checking off.

    var name = 'Alice';          // inferred String, forever
    // name = 42;                // ❌ compile error
    
    dynamic value = 'Alice';
    value = 42;                  // ✅ allowed — no static type
    value.thisDoesNotExist();    // compiles; NoSuchMethodError at runtime
    …
  12. 12

    In Dart, what is the difference between an Exception and an Error, and which one should you catch?

    Medium

    Exception marks a failure your code is expected to anticipate and recover from, while Error signals a bug in the program that you are supposed to fix rather than catch.

    sealed class PaymentFailure implements Exception {
      const PaymentFailure();
    }
    
    class CardDeclined extends PaymentFailure {
      final String code;
    …
  13. 13

    Your assert catches the bad value on every debug run, yet users still hit the crash in the store build — why?

    Easy

    Asserts are compiled out of profile and release builds, so assert is a debug-only check and never input validation.

    class Badge {
      final int count;
      // Checked at compile time for `const Badge(-1)`, and at runtime in debug.
      const Badge(this.count) : assert(count >= 0, 'count cannot be negative');
    }
    …
  14. 14

    A helper assigns a new List to its parameter and the caller sees nothing, yet an add() inside the same helper did change the caller's list — why?

    Easy

    Dart passes every argument by value, but for an object that value is a reference — the callee gets its own copy of the handle, not a copy of the object.

    void reassign(List<int> items) {
      items = [99]; // rebinds the LOCAL handle only
    }
    
    void mutate(List<int> items) {
      items.add(99); // reaches through the handle — caller sees it
    …
  15. 15

    Your code throws "Unsupported operation: Cannot add to a fixed-length list" on a list you built with List.filled — what should you have written?

    Easy

    List.filled returns a fixed-length list by default: elements can be replaced by index, but the length can never change.

    final fixed = List.filled(3, 0);
    fixed[0] = 7;   // ✅ replacing an element is fine
    // fixed.add(1); // ❌ Unsupported operation: Cannot add to a fixed-length list
    
    final growable = List.filled(3, 0, growable: true);
    growable.add(1); // ✅
    …
  16. 16

    A nickname field capped at 20 characters chops an emoji in half and renders a black diamond — what is String.length actually counting?

    Medium

    String.length counts UTF-16 code units, not the characters a person sees.

    import 'package:characters/characters.dart';
    
    const name = 'Ana 👍🇰🇿';
    
    print(name.length);             // 10 — UTF-16 code units
    print(name.runes.length);       // 7  — code points
    …
  17. 17

    A screen keeps rebuilding after dispose even though dispose() calls removeListener(() => _refresh()) — what is wrong with that line?

    Medium

    Every evaluation of () => _refresh() creates a brand-new closure object, and removeListener finds the listener by ==, so it removes nothing and the notifier keeps a reference to your disposed State.

    class _FeedState extends State<Feed> {
      final controller = ScrollController();
    
      @override
      void initState() {
        super.initState();
    …
  18. 18

    A cart total renders as 19.999999999999996, and on Flutter web an order id from JSON comes back off by one digit — what do these two bugs share?

    Medium

    Both are IEEE-754 doubles: double cannot represent 0.1 exactly, and compiled to JavaScript every Dart int is a JS number, which is a double.

    print(0.1 + 0.2);            // 0.30000000000000004
    print(0.1 + 0.2 == 0.3);     // false
    print((0.1 + 0.2).toStringAsFixed(2)); // 0.30 — display only, not a fix
    
    // ❌ accumulating money in doubles
    double totalBad = 0;
    …
  19. 19

    Users abroad see an event an hour off, and a saved DateTime is not equal to the loaded one although both point at the same instant — what does DateTime store?

    Medium

    A DateTime is microseconds since the epoch plus one boolean saying whether it is UTC — it carries no timezone at all.

    final now = DateTime.now();
    print(now.isUtc); // false — local, with the device's offset
    
    // ❌ no Z in the string → parsed as LOCAL, so the instant shifts per device
    final a = DateTime.parse('2026-03-29T10:00:00');
    // ✅ explicit UTC → the same instant everywhere
    …
  20. 20

    The same endpoint parses fine for one product and throws "type 'int' is not a subtype of type 'double'" for another — where does that come from?

    Medium

    jsonDecode gives you an int for 10 and a double for 10.0, and as double on an int is a failing runtime cast — the payload changed its literal, not its schema.

    final json = jsonDecode('{"price": 10, "tags": ["new"], "rating": 4.5}')
        as Map<String, dynamic>;
    
    // ❌ works while the server sends 10.0, throws the day it sends 10
    // final price = json['price'] as double;
    …