Watch the video (8 min)
On this page22 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. A Value Dart Cannot Trust
  5. 2. What Is the Null Assertion Operator?
  6. 3. Using !
  7. 4. Copying into a Non-Nullable Variable
  8. 5. Properties and Methods Through !
  9. 6. When the Promise Is Broken
  10. 7. ! Moves the Error to Run Time
  11. 8. When ! Is Unnecessary
  12. 9. !, ??, or ?.?
  13. 10. A Real-World Example
  14. Code Examples
  15. Common Beginner Mistakes
  16. Best Practices
  17. Mini Challenge
  18. Practice Questions
  19. Practice Answers
  20. Quick Revision
  21. Key Takeaways
  22. What's Next?

Lecture 15 — Null Assertion Operator !

Category3 — Null Safety
Lecture015 of 140
Estimated video length8 min
TargetDart 3.12.2
LevelBeginner

Sometimes you know a nullable value is not null, but Dart can't see it. The null assertion operator ! lets you say "trust me, there is a value" — and crashes the program if you are wrong.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 004–014:

  • declaring variables with a type and with var, and late (Lecture 006)
  • converting text to numbers with int.tryParse and double.tryParse, which return null for invalid text (Lecture 010)
  • the difference between a compile-time error and a run-time crash, and as as a promise (Lecture 011)
  • null, nullable types such as int?, and why Dart refuses to use them directly (Lectures 012–013)
  • the null-aware operators ??, ??=, and ?. (Lecture 014)

Connection With Previous Lectures

In Lecture 014 we handled a possible null by giving a default with ?? or by skipping the work with ?.. Both assume the value really might be missing. But look at this:

dart
void main() {
  int? quantity = int.tryParse('3');
  // int total = quantity * 500; // ✗ quantity is int?
}

The text is '3' — written by us, not typed by a user. It can never fail to parse. A default like ?? 0 would be a lie, because 0 can never happen. We need a way to tell Dart: this value is definitely there.


Learning Objectives

By the end of this lecture you will be able to:

  • Explain what the null assertion operator ! does
  • Use ! to turn a nullable value into a non-nullable one
  • Call properties and methods through !
  • Recognize the run-time error Null check operator used on a null value
  • Explain why ! moves a mistake from compile time to run time
  • Recognize when ! is unnecessary
  • Choose between !, ??, and ?.
  • Use ! only when you can prove a value is not null

1. A Value Dart Cannot Trust

int.tryParse returns an int?: a number, or null if the text is not a number. Dart checks the type, not the text, so it treats every result as possibly missing — even '40':

dart
void main() {
  int? score = int.tryParse('40');
  int total = score + 5;
  print(total);
}
output
Error: Operator '+' cannot be called on 'int?' because it is potentially null.
  int total = score + 5;
                    ^
Error: A value of type 'num' can't be assigned to a variable of type 'int'.
  int total = score + 5;
                    ^

The first message is the real problem; the second is a side effect of it. Your editor's hint even suggests the fix: "Try adding a null check to the target ('!')."


2. What Is the Null Assertion Operator?

The null assertion operator is an exclamation mark written straight after a value: score!. It means: "this value is not null — treat it as non-nullable."

Analogy — think of a signed guarantee. A shopkeeper won't hand over goods for a cheque he can't verify — until you sign "I guarantee this cheque is good". He accepts it at once. But if the cheque bounces, the trouble comes later, and it is yours.

Dart accepts score! straight away. If score really holds null, the trouble comes when the program runs.


3. Using !

Add ! to the nullable value, and the error from Step 1 disappears:

dart
void main() {
  int? score = int.tryParse('40');
  int total = score! + 5;
  print(total);
}
output
45

score has type int?, but score! has type int — so + is allowed and the result fits in an int variable. Also called the null check or bang operator, ! changes only the type Dart sees; the value 40 is untouched.


4. Copying into a Non-Nullable Variable

A nullable value can't go straight into a non-nullable variable (Lecture 013). With !, it can:

dart
void main() {
  int? parsed = int.tryParse('25');
  int age = parsed!;
  print('Age: $age');
}
output
Age: 25

From here on, age is an ordinary int, and you never need ! for it again.


5. Properties and Methods Through !

! also works in front of a dot. Write it between the value and the property or method:

dart
void main() {
  double? price = double.tryParse('1299.5');
  print(price!.toStringAsFixed(2));
  print(price.round());
}
output
1299.50
1300

Notice line two: price.round() needs no !. Once a local variable has passed a ! check, Dart remembers that it is not null for the lines that follow.


6. When the Promise Is Broken

Now give ! a value that really is null:

dart
void main() {
  int? score = int.tryParse('forty');
  print('Calculating...');
  int total = score! + 5;
  print(total);
}
output
Calculating...
Unhandled exception:
Null check operator used on a null value

This compiled without a single complaint. The program started, printed Calculating..., and crashed only when it reached score!. The message says exactly what happened: a null check (!) met a null value.

Dart also prints a few lines showing where the crash happened. We will learn to read them when we cover errors and exceptions, starting in Lecture 083.


7. ! Moves the Error to Run Time

This is the heart of the lecture. Remember compile time vs run time from Lecture 011:

Without !With !
Value is a numbercompile-time errorworks
Value is nullcompile-time errorrun-time crash

Without !, Dart stops you before anything runs — safe. With !, you switch that check off for one value, just as as does in Lecture 011 and late does in Lecture 006. ! is honest only when you can say why the value cannot be null.


8. When ! Is Unnecessary

If Dart can already see that a value is not null, ! does nothing. Here the value is written right on the same line:

dart
void main() {
  String? name = 'Ali';
  print(name!.length);
}
output
3

It runs, but your editor and dart analyze warn you:

output
warning - The '!' will have no effect because the receiver can't be null. Try removing the '!' operator.

The same happens with a non-nullable variable such as String name = 'Ali'; — name! is pointless, because name can never be null. Use ! only for values Dart can't see: results of tryParse, and later, data from users, files, maps, and functions.


9. !, ??, or ?.?

You now have three ways to handle a nullable value. They answer different questions:

dart
void main() {
  int? marks = int.tryParse('abc');
  print(marks ?? 0);
  print(marks?.isEven);
  // print(marks!); // ✗ would crash here
}
output
0
null
OperatorUse it when…If the value is null…
value ?? fallbacka missing value is normal and has a sensible defaultuses the fallback
value?.memberyou want to skip the work when the value is missinggives null
value!the value cannot be missing — you can prove itcrashes

For anything a user types, null is a normal outcome — use ?? or ?.. Keep ! for values that are guaranteed.

The ! written before a bool, as in !isStudent, is a different operator — "not". It belongs to Lecture 019, Logical Operators.


10. A Real-World Example

A shop's checkout reads two numbers as text. The unit price comes from the shop's own price tag, '450' — it is always valid. The quantity is typed by the customer, Zayan, and might be anything:

dart
void main() {
  String priceTag = '450';
  String typedQuantity = 'two';

  int price = int.tryParse(priceTag)!;
  int quantity = int.tryParse(typedQuantity) ?? 1;
  int total = price * quantity;

  print('Price: $price');
  print('Quantity: $quantity');
  print('Total: $total');
}
output
Price: 450
Quantity: 1
Total: 450

The price tag is ours, so ! is a promise we can keep. Zayan's input is not ours, so it gets a safe default with ??. Had we written ! on the quantity, the checkout would have crashed on 'two'.


Code Examples

Example 1 — Turning int? into int

dart
void main() {
  int? parsed = int.tryParse('12');
  int number = parsed!;
  print(number);
}
output
12

Example 2 — Arithmetic Through !

dart
void main() {
  int? a = int.tryParse('8');
  int? b = int.tryParse('7');
  print(a! * b!);
}
output
56

Example 3 — Directly on a Result

dart
void main() {
  int doubled = int.tryParse('21')! * 2;
  print(doubled);
}
output
42

How it works

  1. int.tryParse('21') gives an int?.
  2. ! is applied to that result at once, giving an int, so * 2 is allowed.

Example 4 — A Method Through !

dart
void main() {
  double? weight = double.tryParse('72.456');
  print(weight!.toStringAsFixed(1));
}
output
72.5

Example 5 — Dart Remembers After !

dart
void main() {
  int? steps = int.tryParse('9000');
  print(steps!.isEven);
  print(steps + 1000);
}
output
true
10000

How it works

  1. steps! passes the null check, so Dart now knows steps is not null.
  2. On the next line, steps + 1000 needs no !.

Example 6 — ! Next to ??

dart
void main() {
  int? sure = int.tryParse('5');
  int? unsure = int.tryParse('five');
  print(sure!);
  print(unsure ?? 0);
}
output
5
0

Example 7 — Student Marks

dart
void main() {
  int math = int.tryParse('85')!;
  int science = int.tryParse('90')!;
  int total = math + science;
  print('Student: Sara');
  print('Total: $total');
}
output
Student: Sara
Total: 175

How it works

  1. Both marks are fixed text written in the program, so ! is safe.
  2. After !, each mark is a plain int, and they add normally.

Example 8 — Shopping Total

dart
void main() {
  double price = double.tryParse('249.99')!;
  int quantity = int.tryParse('3')!;
  double total = price * quantity;
  print('Total: ${total.toStringAsFixed(2)}');
}
output
Total: 749.97

Example 9 — Bank Balance

dart
void main() {
  double balance = double.tryParse('5000.0')!;
  double? deposit = double.tryParse('');
  balance = balance + (deposit ?? 0);
  print('Owner: Ali');
  print('Balance: $balance');
}
output
Owner: Ali
Balance: 5000.0

How it works

  1. The starting balance is fixed text, so ! is safe.
  2. The deposit field was left empty — double.tryParse('') gives null — so ?? supplies 0 instead. A ! here would crash.

Example 10 — Temperature Conversion

dart
void main() {
  double? celsius = double.tryParse('30');
  double fahrenheit = celsius! * 9 / 5 + 32;
  print('Celsius: $celsius');
  print('Fahrenheit: $fahrenheit');
}
output
Celsius: 30.0
Fahrenheit: 86.0

How it works

  1. double.tryParse('30') gives the double 30.0, typed as double?.
  2. celsius! makes the arithmetic allowed; the result fits in a double.

Common Beginner Mistakes

1. Using a nullable value without handling it

dart
void main() {
  int? score = int.tryParse('40');
  // int total = score + 5; // ✗
}
output
Error: Operator '+' cannot be called on 'int?' because it is potentially null.

Decide first: is null possible? If not, write score!. If it is, use score ?? 0.

2. Using ! on a value that can be null

dart
void main() {
  int? age = int.tryParse('twenty');
  // print(age! + 1); // ✗ compiles, then crashes
}
output
Unhandled exception:
Null check operator used on a null value

! does not fix a missing value — it only promises there isn't one. Use ?? for text that might be invalid.

3. Thinking ! turns null into 0

dart
void main() {
  int? bonus = int.tryParse('');
  // int points = bonus!; // ✗ crashes — it does not become 0
}
output
Unhandled exception:
Null check operator used on a null value

For "use 0 when missing", write bonus ?? 0.

4. Putting ! in the wrong place

dart
void main() {
  int? n = int.tryParse('5');
  // print((n + 1)!); // ✗
}
output
Error: Operator '+' cannot be called on 'int?' because it is potentially null.

! belongs on the nullable value itself, before you use it: n! + 1.

5. Adding ! where nothing can be null

dart
void main() {
  String name = 'Ali';
  // print(name!.length); // ⚠ runs, but warns
}
output
warning - The '!' will have no effect because the receiver can't be null. Try removing the '!' operator.

Remove the !. A ! should always mean "this could be null, but here it isn't".


Best Practices

  • Use ! only when you can explain in one sentence why the value cannot be null.
  • Never use ! just to make a compile-time error go away.
  • For anything that comes from a user, prefer ?? or ?. to !.
  • Apply ! once, into a non-nullable variable (int age = parsed!;), instead of repeating it on every line.
  • Remove a ! when your editor says it has no effect.
  • If you find yourself writing many !s, rethink the types — maybe the variable should not be nullable at all.

Mini Challenge

A gym records Sara's weight as text. Her starting weight '68.4' comes from the gym's own scale, and her lost weight '2.9' comes from the same scale. Convert both and print her new weight with one decimal place.

Your program should print exactly:

output
New weight: 65.5 kg

Try it yourself before opening the solution.

Show solution
dart
void main() {
  double start = double.tryParse('68.4')!;
  double lost = double.tryParse('2.9')!;
  double current = start - lost;
  print('New weight: ${current.toStringAsFixed(1)} kg');
}
output
New weight: 65.5 kg

How it works

  1. Both values come from a trusted scale, so ! is a promise we can keep.
  2. After !, both are plain doubles, so subtraction is allowed.
  3. toStringAsFixed(1) shows one decimal place.

Practice Questions

Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.

Beginner

  1. Declare int? parsed = int.tryParse('15');. Copy it into an int variable named count using !, and print count.

  2. Use ! to print the result of int.tryParse('9') multiplied by 9.

  3. Which of these lines crash when run? Answer first, then check by running each one separately.

    dart
    print(int.tryParse('7')!);
    print(int.tryParse('seven')!);
    print(int.tryParse('7') ?? 0);
    print(int.tryParse('seven') ?? 0);

Application

  1. Declare double? price = double.tryParse('99.999');. Use ! to print it with two decimal places.

  2. This program does not compile. Fix it by adding one character, so that it prints 30:

    dart
    void main() {
      int? width = int.tryParse('6');
      int area = width * 5;
      print(area);
    }
  3. Ali's marks are fixed text: '72' and '64'. Use ! to convert both and print Total: 136.

  4. This program compiles but crashes. Explain in one sentence why, then fix it without using ! so it prints Points: 0:

    dart
    void main() {
      int? points = int.tryParse('none');
      print('Points: ${points!}');
    }
  5. Declare int? year = int.tryParse('2026');. Use ! once to print whether it is even, then print year + 1 on the next line without another !.

Challenge

  1. Zayan's account starts at the fixed text '1200.0'. He types a withdrawal of 'abc'. Convert the balance with ! and the withdrawal with ?? (default 0), and print Balance: 1200.0. Explain in one sentence why each operator was the right choice.
  2. A thermometer sends the fixed reading '21.5' in Celsius. Convert it with !, then print Fahrenheit: 70.7.

Practice Answers

Question 1 — Solution

dart
void main() {
  int? parsed = int.tryParse('15');
  int count = parsed!;
  print(count);
}
output
15

Question 2 — Solution

dart
void main() {
  print(int.tryParse('9')! * 9);
}
output
81

Question 3 — Solution

Only the second line crashes: 'seven' is not a number, so tryParse gives null, and ! meets it.

dart
void main() {
  print(int.tryParse('7')!);
  print(int.tryParse('7') ?? 0);
  print(int.tryParse('seven') ?? 0);
}
output
7
7
0

Run alone, the second line prints:

output
Unhandled exception:
Null check operator used on a null value

Question 4 — Solution

dart
void main() {
  double? price = double.tryParse('99.999');
  print(price!.toStringAsFixed(2));
}
output
100.00

Question 5 — Solution

Add ! after width:

dart
void main() {
  int? width = int.tryParse('6');
  int area = width! * 5;
  print(area);
}
output
30

Question 6 — Solution

dart
void main() {
  int first = int.tryParse('72')!;
  int second = int.tryParse('64')!;
  print('Total: ${first + second}');
}
output
Total: 136

Question 7 — Solution

It crashes because 'none' is not a number, so points is null — and ! promised it wasn't. Use ?? instead:

dart
void main() {
  int? points = int.tryParse('none');
  print('Points: ${points ?? 0}');
}
output
Points: 0

Question 8 — Solution

dart
void main() {
  int? year = int.tryParse('2026');
  print(year!.isEven);
  print(year + 1);
}
output
true
2027

After year! passes, Dart knows year is not null, so the second line needs no !.

Question 9 — Solution

dart
void main() {
  double balance = double.tryParse('1200.0')!;
  double withdrawal = double.tryParse('abc') ?? 0;
  balance = balance - withdrawal;
  print('Balance: $balance');
}
output
Balance: 1200.0

The balance is fixed text that always parses, so ! is a safe promise; the withdrawal is typed by a person and may be invalid, so it needs a default.

Question 10 — Solution

dart
void main() {
  double celsius = double.tryParse('21.5')!;
  double fahrenheit = celsius * 9 / 5 + 32;
  print('Fahrenheit: $fahrenheit');
}
output
Fahrenheit: 70.7

Quick Revision

  1. What does ! written after a value do?
  2. What type is score! when score is an int??
  3. What is the exact error message when ! meets null?
  4. Is that a compile-time error or a run-time error?
  5. Why doesn't Dart need ! on price after price! has run once?
  6. What warning appears when you use ! on a value that can't be null?
  7. Which operator should you choose for text a user types: ! or ??? Why?

Key Takeaways

  • The null assertion operator ! is written after a value and turns T? into T.
  • It changes only the type Dart sees — the value itself is untouched.
  • ! works in calculations, assignments, and before a dot: price!.round().
  • If the value is null, the program stops with Null check operator used on a null value.
  • ! replaces a safe compile-time error with a possible run-time crash.
  • After a local variable passes !, Dart knows it is not null on the following lines.
  • ! on a value that can't be null has no effect, and Dart warns you.
  • Use ?? or ?. when null is possible; use ! only when you can prove it isn't.

What's Next?

Lecture 016 — Null Safety in Real Code. You now know every null-safety tool: nullable types, ??, ??=, ?., and !. Next we bring them together in realistic programs — user input, optional details, values that arrive late — and practice choosing the right tool for each situation, so null safety becomes a habit instead of a puzzle.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.