Watch the video (8 min)
On this page25 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Two Ways to Hold "Any Value"
  5. 2. Every Value Is an Object
  6. 3. Declaring an Object Variable
  7. 4. What You Can Do with an Object
  8. 5. What You Cannot Do with an Object
  9. 6. Using the Real Value with as
  10. 7. Declaring a dynamic Variable
  11. 8. dynamic Switches the Checks Off
  12. 9. Compile Time vs Run Time
  13. 10. Copying into a Specific Type
  14. 11. var, Object, and dynamic Side by Side
  15. 12. Which One Should You Use?
  16. 13. A Real-World Example
  17. Code Examples
  18. Common Beginner Mistakes
  19. Best Practices
  20. Mini Challenge
  21. Practice Questions
  22. Practice Answers
  23. Quick Revision
  24. Key Takeaways
  25. What's Next?

Lecture 11 — dynamic vs Object

Category2 — Variables & Data Types
Lecture011 of 140
Estimated video length8 min
TargetDart 3.12.2
LevelBeginner

Every variable so far held one kind of value. Object and dynamic both let a variable hold any value — but one keeps Dart checking your code, and the other switches the checks off.

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–010:

  • declaring variables with an explicit type and with var
  • why var score; without a value lets any value in (Lecture 005)
  • the types String, int, double, and bool, and string properties such as length
  • checking a type with is, reading it with runtimeType, and casting with as (Lecture 010)

Connection With Previous Lectures

Every variable we have written has one fixed type:

dart
var age = 20; // an int, forever

But some values can be of different kinds: a setting might be true, 25, or 'dark'. No type we know holds all three. In Lecture 005, var score; accepted anything — and quietly turned type checking off. This lecture shows the two proper ways to hold "any value", and why they behave very differently.


Learning Objectives

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

  • Explain why every value in Dart is an Object
  • Declare variables of type Object and dynamic
  • Recognize what Dart allows you to do with an Object value
  • Use as to work with the real value inside an Object variable
  • Explain how dynamic switches off compile-time type checking
  • Tell a compile-time error from a run-time crash
  • Compare var, Object, and dynamic
  • Choose the safest type for a variable

1. Two Ways to Hold "Any Value"

Dart gives you two types that accept a value of any kind: Object and dynamic.

Analogy — imagine two boxes that hold anything. The Object box is sealed and labeled "something": you can carry it and show it, but before using what is inside you must say what it is. The dynamic box is open: Dart trusts you to use the contents correctly, and if you guessed wrong you find out only while the program runs.

Both hold the same values. What differs is how much Dart checks.


2. Every Value Is an Object

Object is the most general type in Dart. Every value you have met — text, whole numbers, decimals, true and false — is an Object:

dart
void main() {
  print('Ali' is Object);
  print(20 is Object);
  print(99.5 is Object);
  print(true is Object);
}
output
true
true
true
true

Your editor may underline these lines with "Unnecessary type check; the result is always 'true'" — Dart already knows the answer. A String is a String and an Object, just as Ali is a student and also a person.


3. Declaring an Object Variable

Because every value is an Object, a variable of type Object can hold any of them, and can be changed to a value of a different kind:

dart
void main() {
  Object item = 'Ali';
  print(item);
  item = 20;
  print(item);
  item = true;
  print(item);
}
output
Ali
20
true

runtimeType (Lecture 010) shows what kind of value is inside right now:

dart
void main() {
  Object item = 'Ali';
  print(item.runtimeType);
  item = 20;
  print(item.runtimeType);
}
output
String
int

4. What You Can Do with an Object

Dart only lets you do with an Object variable what works for every value: print it, put it in a string, convert it with toString(), compare it with ==, and read its runtimeType.

dart
void main() {
  Object price = 250;
  print(price);
  print('Price: $price');
  print(price.toString());
  print(price == 250);
}
output
250
Price: 250
250
true

5. What You Cannot Do with an Object

length belongs to strings, not to every value. Dart sees only the type Object, so it refuses — even though the value inside really is a String:

dart
void main() {
  Object item = 'Ali';
  print(item.length);
}
output
Error: The getter 'length' isn't defined for the type 'Object'.
 - 'Object' is from 'dart:core'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
  print(item.length);
             ^^^^^^

Arithmetic is refused for the same reason — not every value can be added:

dart
void main() {
  Object price = 100;
  print(price + 50);
}
output
Error: The operator '+' isn't defined for the type 'Object'.
 - 'Object' is from 'dart:core'.
Try correcting the operator to an existing operator, or defining a '+' operator.
  print(price + 50);
              ^

These are compile-time errors: Dart stops before the program runs a single line.


6. Using the Real Value with as

To use the value as what it really is, tell Dart with as (Lecture 010). The parentheses make the cast happen first:

dart
void main() {
  Object item = 'Ali';
  print((item as String).length);

  Object price = 100;
  print((price as int) + 50);
}
output
3
150

as is a promise. If the promise is wrong, the program crashes while running:

dart
void main() {
  Object item = 20;
  print((item as String).length);
}
output
Unhandled exception:
type 'int' is not a subtype of type 'String' in type cast

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. Check with is before you cast when you are not sure; in Lecture 022, if will let you act on that check.


7. Declaring a dynamic Variable

A dynamic variable also holds any value and can change kind:

dart
void main() {
  dynamic value = 'Sara';
  print(value);
  value = 18;
  print(value);
}
output
Sara
18

The difference shows when you use the value. With dynamic, Dart lets you write anything — no cast needed:

dart
void main() {
  dynamic name = 'Sara';
  print(name.length);
  print(name.toUpperCase());
}
output
4
SARA

8. dynamic Switches the Checks Off

Dart did not check name.length — it simply trusted you. When the trust is misplaced, the mistake is not caught before the program runs. It crashes instead:

dart
void main() {
  dynamic value = 20;
  print(value.length);
}
output
Unhandled exception:
NoSuchMethodError: Class 'int' has no instance getter 'length'.
Receiver: 20
Tried calling: length

Even a simple typo slips through:

dart
void main() {
  dynamic name = 'Sara';
  print(name.toUpperCse());
}
output
Unhandled exception:
NoSuchMethodError: Class 'String' has no instance method 'toUpperCse'.
Receiver: "Sara"
Tried calling: toUpperCse()

With Object or String, Dart would have pointed at this typo before running anything.


9. Compile Time vs Run Time

This is the heart of the lecture.

  • A compile-time error appears before the program starts. Nothing runs. Safe.
  • A run-time error appears while the program runs — perhaps halfway through its work, perhaps only on a user's computer. Dangerous.
MistakeWith ObjectWith dynamic
Using length on a valuecompile-time errorallowed — crashes if the value has none
A typo in a method namecompile-time errorcrashes when that line runs
Adding with +compile-time errorallowed — crashes if the value can't be added

Object makes you prove your intent with as. dynamic takes your word for it.


10. Copying into a Specific Type

The same difference appears when you copy the value into a typed variable. From Object, Dart demands a cast:

dart
void main() {
  Object item = 'Ali';
  String name = item;
  print(name);
}
output
Error: A value of type 'Object' can't be assigned to a variable of type 'String'.
 - 'Object' is from 'dart:core'.
  String name = item;
                ^

Write String name = item as String; and it runs. From dynamic, Dart allows the copy without asking — and crashes if the value is the wrong kind:

dart
void main() {
  dynamic value = 20;
  String name = value;
  print(name);
}
output
Unhandled exception:
type 'int' is not a subtype of type 'String'

11. var, Object, and dynamic Side by Side

dart
void main() {
  var a = 10; // int — fixed type
  Object b = 10; // any value, checked
  dynamic c = 10; // any value, unchecked

  b = 'ten';
  c = 'ten';
  print(a);
  print(b);
  print(c);
}
output
10
ten
ten
Holds any value?Dart checks how you use it?
var a = 10;No — int onlyYes
Object b = 10;YesYes
dynamic c = 10;YesNo

Writing a = 'ten'; would be an error, as in Lecture 005. And remember var score; with no value: that variable is dynamic, which is why it accepted anything.


12. Which One Should You Use?

Pick the most specific type that fits:

  1. A specific type (String, int, …) or var — almost always.
  2. Object — when a value truly can be of any kind. Dart keeps checking for you.
  3. dynamic — only when you must, such as data from outside the program. You will meet this with JSON in Lectures 108–109.

There is one more difference, to do with missing values — we will meet it in Lectures 012–013.


13. A Real-World Example

A sign-up form gives us two answers. The name arrives as text; the age arrives as text too, because people type it. We hold both as Object, and use as to say what each one is:

dart
void main() {
  Object nameAnswer = 'Zayan';
  Object ageAnswer = '6';

  var name = nameAnswer as String;
  var age = int.parse(ageAnswer as String);

  print('Name: ${name.toUpperCase()}');
  print('Letters: ${name.length}');
  print('Age next year: ${age + 1}');
  print('Answer types: ${nameAnswer.runtimeType}, ${ageAnswer.runtimeType}');
}
output
Name: ZAYAN
Letters: 5
Age next year: 7
Answer types: String, String

After as String, name is a real String with toUpperCase() and length, and int.parse (Lecture 010) turns the age text into an int. Dart checked every step before the program ran.


Code Examples

Example 1 — Every Value Is an Object

dart
void main() {
  print('Sara' is Object);
  print(42 is Object);
  print(3.5 is Object);
  print(false is Object);
}
output
true
true
true
true

Example 2 — An Object Variable Changing Kind

dart
void main() {
  Object item = 'Ali';
  print('$item is a ${item.runtimeType}');
  item = 7.5;
  print('$item is a ${item.runtimeType}');
}
output
Ali is a String
7.5 is a double

Example 3 — Casting an Object with as

dart
void main() {
  Object word = 'Dart';
  var text = word as String;
  print(text.length);
  print(text.toUpperCase());
}
output
4
DART

Example 4 — A dynamic Variable Changing Kind

dart
void main() {
  dynamic value = 10;
  print(value.runtimeType);
  value = 'ten';
  print(value.runtimeType);
}
output
int
String

Example 5 — Using dynamic Without a Cast

dart
void main() {
  dynamic city = 'Lahore';
  print(city.length);
  print(city.toLowerCase());
}
output
6
lahore

Example 6 — Checking Before You Cast

dart
void main() {
  Object answer = 25;
  print(answer is int);
  print(answer is String);
  print((answer as int) * 2);
}
output
true
false
50

How it works

  1. answer is int prints true, so casting to int is safe.
  2. answer is String prints false — casting to String would crash.
  3. After as int, multiplication is allowed: 25 * 2 is 50.

Example 7 — Student Marks

dart
void main() {
  Object student = 'Ali';
  Object math = 80;
  Object science = 75;

  var total = (math as int) + (science as int);
  print('Student: $student');
  print('Total: $total');
}
output
Student: Ali
Total: 155

How it works

  1. student is only printed, which works for every Object — no cast needed.
  2. The marks must be added, so each is cast to int first.

Example 8 — Shopping Total

dart
void main() {
  Object product = 'Notebook';
  Object price = 500;
  Object quantity = '3';

  var total = (price as int) * int.parse(quantity as String);
  print('Product: $product');
  print('Total: $total');
}
output
Product: Notebook
Total: 1500

How it works

  1. price holds an int, so as int is enough.
  2. quantity holds the text '3', so it is cast to String and converted with int.parse.
  3. Casting quantity straight to int would crash: the value is a String, not an int.

Example 9 — Bank Balance

dart
void main() {
  Object owner = 'Sara';
  Object balance = 1000.0;
  Object deposit = 250.5;

  var newBalance = (balance as double) + (deposit as double);
  print('Owner: $owner');
  print('Balance: $newBalance');
}
output
Owner: Sara
Balance: 1250.5

How it works

  1. Both amounts hold a double, so each is cast to double before adding.
  2. newBalance is inferred as double: 1250.5.

Example 10 — Temperature with dynamic

dart
void main() {
  dynamic celsius = 25.0;
  var fahrenheit = celsius * 9 / 5 + 32;
  print('Celsius: $celsius');
  print('Fahrenheit: $fahrenheit');
  print(fahrenheit.runtimeType);
}
output
Celsius: 25.0
Fahrenheit: 77.0
double

How it works

  1. celsius is dynamic, so Dart allows the arithmetic without a cast.
  2. A calculation on a dynamic value gives a dynamic result, so fahrenheit is inferred as dynamic too — the unchecked type spreads.
  3. runtimeType still reports the real value, a double.

Common Beginner Mistakes

1. Using a String property on an Object variable

dart
void main() {
  Object item = 'Ali';
  // print(item.length); // ✗
}
output
Error: The getter 'length' isn't defined for the type 'Object'.

Cast first: (item as String).length.

2. Doing arithmetic on an Object variable

dart
void main() {
  Object price = 100;
  // print(price + 50); // ✗
}
output
Error: The operator '+' isn't defined for the type 'Object'.

Write (price as int) + 50.

3. Copying an Object into a typed variable without a cast

dart
void main() {
  Object item = 'Ali';
  // String name = item; // ✗
}
output
Error: A value of type 'Object' can't be assigned to a variable of type 'String'.

Write String name = item as String;.

4. Casting to the wrong type

dart
void main() {
  Object item = 20;
  // print((item as String).length); // ✗ crashes while running
}
output
Unhandled exception:
type 'int' is not a subtype of type 'String' in type cast

as does not convert — it only promises. Check with is first, or convert with the tools from Lecture 010 (toString(), int.parse).

5. Using dynamic to make an error go away

dart
void main() {
  dynamic value = 20;
  // print(value.length); // ✗ compiles, then crashes
}
output
Unhandled exception:
NoSuchMethodError: Class 'int' has no instance getter 'length'.

dynamic does not fix the mistake — it hides it until the program runs.


Best Practices

  • Use a specific type or var whenever you know what kind of value a variable holds.
  • When a value really can be of any kind, prefer Object to dynamic.
  • Keep dynamic for data from outside the program, and convert it to a specific type as soon as possible.
  • Cast once into a new, typed variable (var name = item as String;) instead of casting again on every line.
  • Check with is before casting when you are not sure what a value is.
  • Always initialize var variables, so they never become dynamic by accident.

Mini Challenge

A quiz app stores Sara's answers as Object: her name 'Sara', her score 45, and the bonus points as the text '5'. Print her name in capitals and her final score.

Your program should print exactly:

output
Player: SARA
Final score: 50

Try it yourself before opening the solution.

Show solution
dart
void main() {
  Object player = 'Sara';
  Object score = 45;
  Object bonus = '5';

  var name = player as String;
  var finalScore = (score as int) + int.parse(bonus as String);
  print('Player: ${name.toUpperCase()}');
  print('Final score: $finalScore');
}
output
Player: SARA
Final score: 50

How it works

  1. player is cast to String so toUpperCase() is available.
  2. score holds an int; bonus holds text, so it is cast to String and parsed.
  3. 45 + 5 gives 50.

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 Object item = 'Karachi';, print it, then change it to 2026 and print it again.
  2. Print whether 12, 'Ali', and false are each an Object, one result per line.
  3. Declare dynamic value = 3.5; and print its runtimeType. Then assign 'three' to it and print its runtimeType again.

Application

  1. Declare Object word = 'Flutter';. Use as to print the number of letters in it.

  2. Declare Object price = 450;. Use as to print the price after adding 50.

  3. This program does not compile. Fix it without changing the type Object, so that it prints ZAYAN:

    dart
    void main() {
      Object name = 'Zayan';
      print(name.toUpperCase());
    }
  4. Predict the output without running it, then check. Which line would be a compile-time error if x were declared as Object instead?

    dart
    void main() {
      dynamic x = 'Ali';
      print(x.length);
      x = 7;
      print(x * 3);
    }
  5. Ali's marks are stored as Object math = 70; and Object english = 88;. Print Total: 158.

Challenge

  1. A form stores Object balanceText = '1500'; and Object deposit = 500;. Print Balance: 2000.

  2. This program compiles but crashes. Explain in one sentence why, then fix it by changing one line so it prints Letters: 2:

    dart
    void main() {
      dynamic age = 25;
      print('Letters: ${age.length}');
    }

Practice Answers

Question 1 — Solution

dart
void main() {
  Object item = 'Karachi';
  print(item);
  item = 2026;
  print(item);
}
output
Karachi
2026

Question 2 — Solution

dart
void main() {
  print(12 is Object);
  print('Ali' is Object);
  print(false is Object);
}
output
true
true
true

Question 3 — Solution

dart
void main() {
  dynamic value = 3.5;
  print(value.runtimeType);
  value = 'three';
  print(value.runtimeType);
}
output
double
String

Question 4 — Solution

dart
void main() {
  Object word = 'Flutter';
  print((word as String).length);
}
output
7

Question 5 — Solution

dart
void main() {
  Object price = 450;
  print((price as int) + 50);
}
output
500

Question 6 — Solution

Cast the value to String before calling toUpperCase():

dart
void main() {
  Object name = 'Zayan';
  print((name as String).toUpperCase());
}
output
ZAYAN

Question 7 — Solution

dart
void main() {
  dynamic x = 'Ali';
  print(x.length);
  x = 7;
  print(x * 3);
}
output
3
21

With Object, both x.length and x * 3 would be compile-time errors.

Question 8 — Solution

dart
void main() {
  Object math = 70;
  Object english = 88;
  var total = (math as int) + (english as int);
  print('Total: $total');
}
output
Total: 158

Question 9 — Solution

dart
void main() {
  Object balanceText = '1500';
  Object deposit = 500;
  var balance = int.parse(balanceText as String) + (deposit as int);
  print('Balance: $balance');
}
output
Balance: 2000

balanceText holds text, so it is cast to String and parsed; deposit already holds an int.

Question 10 — Solution

It crashes because age holds an int, which has no length — and dynamic hid that mistake until the program ran. Convert the number to text first:

dart
void main() {
  dynamic age = 25;
  print('Letters: ${age.toString().length}');
}
output
Letters: 2

Quick Revision

  1. Why can an Object variable hold any value?
  2. Which five things can you do with any Object?
  3. What does as do, and what happens if the cast is wrong?
  4. What does dynamic switch off?
  5. What is the difference between a compile-time error and a run-time error?
  6. Which is safer for "any value": Object or dynamic? Why?
  7. What type does var score; (no value) give a variable?

Key Takeaways

  • Every value in Dart is an Object.
  • Both Object and dynamic variables can hold any value and change kind.
  • Object keeps type checking on: you may only do what works for every value until you cast with as.
  • dynamic switches type checking off: anything compiles, and mistakes become run-time crashes.
  • Compile-time errors are safe; run-time errors reach the running program.
  • as promises a type — it does not convert one.
  • var without a value creates a dynamic variable.
  • Prefer a specific type, then Object, and use dynamic only when you must.

What's Next?

Lecture 012 — Introduction to Null Safety. So far every variable has held a real value. But real programs often deal with values that are missing — a middle name nobody entered, a score not recorded yet. Dart has a special value for "nothing", null, and a system that stops it from crashing your programs. That is where Category 3 begins.


Video lecture

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