Data Types in Dart

By Syncfusion®, Inc. · Last updated

The basic Dart types (int, double, num, String, bool, dynamic, Object, Null, Never), how Dart infers types, and how to check, convert, parse and cast values.

What Is a Data Type?

Data type = the kind of value a variable holds.

For example:

  • 13 is a whole number
  • 1.52 is a decimal number
  • 'Asha' is text
  • true is a yes-or-no answer

Each kind has its own name in Dart, like int or String. The type decides what you can do with the value.

Simple lesson: every value in Dart has a type, and the type says what kind of value it is.

A Real-World Example

Think of the school lab cupboard.

  • Liquids go in bottles.
  • Powders go in jars.
  • Long rods go in boxes.
  • Nobody pours water into a box, because it would leak.

Dart's types are those containers. An int variable holds whole numbers, and Dart will not let you pour text into it.

Every Run box on this page runs on the course's Dart runner in your browser.

Some boxes fail on purpose, to show a real type error.

What You Will Learn

In this lesson, you will learn:

  1. Why types matter, and the number, text and true/false types.
  2. The special types: dynamic, Object, Null and Never.
  3. How Dart infers types with var and final.
  4. How to check a type with is and runtimeType.
  5. How to convert text to numbers and back, and how to cast safely.

Why Data Types Matter

Strong Typing

Strongly typed = every variable has a type, and Dart checks it.

  • You can write the type: int age = 13;
  • Or let Dart work it out: var age = 13; (see below)
  • Either way, age is an int and stays an int.

Type Safety

Type safety = Dart stops you from using a value of the wrong type.

Run this. Text is put into a number box:

Text cannot go into an int

void main() {
  int age = 'thirteen';
  print(age);
}

Dart says: A value of type 'String' can't be assigned to a variable of type 'int'.

  • The mistake is found before the program runs.
  • So it never reaches a user's phone.

Simple lesson: Dart checks types early, so many mistakes never reach the running program.

Numeric Types

int

int = a whole number, with no decimal point.

  • Examples: 13, 0, -5, 2026
  • Use it for counts: students, marks, roll numbers, years.

double

double = a number with a decimal point.

  • Examples: 1.52, 99.5, -0.25
  • Use it for measurements: height, price, temperature, percentage.

num

num = any number, either an int or a double.

  • Use it when a value could be either kind.
  • int and double are both kinds of num.

int, double and num

void main() {
  int students = 450;
  int temperature = -3;
  double height = 1.52;
  double price = 99.5;
  num anyNumber = 7;
  anyNumber = 2.5;

  print('Students: $students');
  print('Temperature: $temperature');
  print('Height: $height m');
  print('Price: ₹$price');
  print('Any number: $anyNumber');
}

anyNumber started as 7 and became 2.5. A num box accepts both kinds.

A double Always Shows Its Decimal Point

A double with a whole value still prints with .0:

double fee = 50;
print(fee);

The output is 50.0, not 50. Dart remembers it is a decimal number.

In real Dart, a whole-number double always prints with .0.

In this course's runner, it may print without the .0. The examples on these pages avoid that case.

Simple lesson: int is for whole numbers, double is for decimals, and num accepts both.

String Type

String = text: letters, digits, spaces and symbols, inside quotes.

String literal = text written straight into your code, like 'Asha'.

  • Single quotes: 'Green Valley'
  • Double quotes: "Green Valley"
  • Both mean the same. Most Dart code uses single quotes.

Strings

void main() {
  String name = 'Kavya';
  String city = "Chennai";
  String rollNumber = '0021';
  print('$name lives in $city.');
  print('Roll number: $rollNumber');
}

'0021' is text, not a number. It keeps its zeros because it is a String.

You will learn much more in Strings.

Simple lesson: anything inside quotes is a String, even if it looks like a number.

Boolean Type

bool = a value that is either true or false.

  • true = yes.
  • false = no.
  • Write them in small letters, without quotes.

true or false

void main() {
  bool isPresent = true;
  bool hasPaidFees = false;
  bool passed = 72 >= 35;
  print('Present: $isPresent');
  print('Fees paid: $hasPaidFees');
  print('Passed: $passed');
}

72 >= 35 asks a question. The answer, true, is stored in passed.

A good bool name sounds like a question: isPresent, hasPaidFees, canVote.

Simple lesson: bool holds yes or no, and it decides what a program does next.

Sort the Values by Type

Click a value, then click its type

Watch the quotes:

  • With quotes, a value is always a String.
  • Without quotes, 42 is an int and true is a bool.

Special Types

Click each special type

dynamic

dynamic = a type that turns off Dart's checking. The value can be anything, and it can change type.

Dynamic typing = the type is only known while the program runs.

A dynamic variable changes type

void main() {
  dynamic box = 5;
  print('$box is a ${box.runtimeType}');
  box = 'five';
  print('$box is a ${box.runtimeType}');
  box = true;
  print('$box is a ${box.runtimeType}');
}

runtimeType tells you the type of the value right now. You will use it again below.

When to use dynamic:

  • Rarely. Usually for data whose shape you do not know yet, like some JSON from a server (see File Handling).
  • Not to avoid thinking about types. Dart stops warning you, so mistakes reach the running program.

Null

null = no value at all, an empty box.

A variable that holds nothing

void main() {
  String? nickname;
  print(nickname);
  nickname = 'Chotu';
  print(nickname);
}
  • String? = a String, or null.
  • A variable with ? and no value starts as null.
  • A plain String can never be null. Dart checks this.

You will learn this properly in Null Safety.

Never

Never = a type with no values. A function that returns Never never finishes normally.

  • Most beginners never write it.
  • You may see it in error messages or library code.

Simple lesson: avoid dynamic, use ? when a value may be missing, and leave Never to libraries.

Choosing the Right Type

The value is...UseExample
A countintint students = 450;
A measurement or moneydoubledouble height = 1.52;
Text, or digits you never do maths onStringString phone = '9876543210';
Yes or noboolbool isPresent = true;
Maybe missingadd ?String? nickname;

Easy way to remember

Ask: "Will I do maths with it?"

  • Yes, whole numbers: int.
  • Yes, decimals: double.
  • No, like a phone number or PIN code: String.

Simple lesson: pick the type that matches what the value means, not just what it looks like.

What Is Type Inference?

Type inference = Dart works out the type of a variable from its first value.

For example:

  • var age = 13; makes age an int
  • var height = 1.52; makes height a double
  • var name = 'Asha'; makes name a String

You did not write the type, but Dart knows it, and it checks it like any other type.

Simple lesson: with var or final, Dart reads the value and picks the type for you.

A Real-World Example

A school form asks for marks in a text box.

  • What you type, like 85, arrives as text: '85'.
  • You cannot add text like numbers. '85' and '90' would just join into '8590'.
  • So the program first converts the text into the number 85.

This lesson teaches both ideas: how Dart knows types, and how to change one type into another.

Some boxes use the Input box on the right. Change the input and press Run again.

Type Inference with var and final

Dart picks the types

void main() {
  var students = 450;
  var fee = 1250.5;
  var school = 'Green Valley';
  final isOpen = true;

  print(students.runtimeType);
  print(fee.runtimeType);
  print(school.runtimeType);
  print(isOpen.runtimeType);
}
  • var and final both use inference.
  • The type is fixed after the first value.

The Type Stays Fixed

Inference does not mean "any type". Run this:

An inferred type cannot change

void main() {
  var marks = 90;
  marks = 'ninety';
  print(marks);
}

Dart says: A value of type 'String' can't be assigned to a variable of type 'int'.

marks became an int on line 2, and it stays an int.

Simple lesson: inference picks the type once, and Dart keeps checking it after that.

Explicit Types vs Type Inference

Explicit type = you write the type yourself: int age = 13;

Both are correct. Compare them.

Write the type yourself when:

  • the variable starts without a value: int total;
  • you want a wider type than the value: num price = 10;
  • the value does not make the type obvious

Simple lesson: let Dart infer obvious types, and write the type when it helps the reader.

Type Checking

Type checking = making sure each value has the right type.

Dart does it at two times:

  • Compile-time checking = before the program runs. Dart reads your code and stops on type mistakes.
  • Runtime checking = while the program runs. You ask about a value with is or runtimeType.

The is Operator

is = asks "is this value of that type?" The answer is true or false.

is! = the opposite: "is it NOT of that type?"

Asking about types with is

void main() {
  var answer = 42;
  print(answer is int);
  print(answer is num);
  print(answer is String);
  print(answer is! double);
}

42 is an int, and every int is also a num.

runtimeType

runtimeType = the exact type of a value, right now.

  • Use it to look at a type while learning or fixing a bug.
  • Use is in real code, to decide something.

Simple lesson: Dart checks types before running, and is lets you check them while running.

Converting Text to Numbers

Text from a user, a file or the internet is a String. To do maths with it, you must convert it.

Explicit conversion = you ask Dart to turn one type into another.

int.parse()

int.parse(text) = turns text like '85' into the int 85.

Press Next step to watch the text become a number.

From text to number

Now with real input. Type two marks in the Input box, one per line:

Adding two marks typed by the user

import 'dart:io';

void main() {
  print('Maths marks:');
  int maths = int.parse(stdin.readLineSync()!);
  print('Science marks:');
  int science = int.parse(stdin.readLineSync()!);
  print('Total: ${maths + science}');
}

The ! after readLineSync() says "I am sure there is a line here". You will learn it in Null Safety.

double.parse() and num.parse()

  • double.parse(text) = turns text into a double.
  • num.parse(text) = gives an int for '12' and a double for '2.5'.

Parsing decimals

void main() {
  var height = double.parse('1.48');
  var bonus = num.parse('2.5');
  var count = num.parse('12');
  print(height + 0.02);
  print(bonus + 1);
  print(count.runtimeType);
}

When Parsing Fails

int.parse() needs digits only. Run this:

parse() cannot read words

void main() {
  var marks = int.parse('ninety');
  print(marks);
}

The program crashes with a FormatException. The text could not be read as a number.

Simple lesson: parse() turns text into a number, but it crashes on text that is not a number.

Safe Parsing with tryParse()

tryParse(text) = like parse(), but gives null instead of crashing.

Compare parse and tryParse

Add ?? 0 to use a default when the text was not a number:

A safe way to read marks

import 'dart:io';

void main() {
  print('Enter marks:');
  var text = stdin.readLineSync() ?? '';
  var marks = int.tryParse(text);
  print('tryParse gave: $marks');
  var safeMarks = int.tryParse(text) ?? 0;
  print('Using: $safeMarks');
}

Change the input to 70 and press Run again.

  • int.tryParse(text) gives a number, or null.
  • ?? 0 means "if it is null, use 0 instead" (see Null Safety).
  • double.tryParse() works the same way for decimals.

Simple lesson: use tryParse() for anything a person types, so a typo never crashes your app.

Converting Numbers to Text

toString()

toString() = turns any value into a String.

Numbers become text

void main() {
  int marks = 92;
  String text = marks.toString();
  print(text + ' out of 100');

  double average = 87.456;
  print(average.toStringAsFixed(1));
  print(average.toStringAsFixed(2));
}
  • toString() lets you join a number with other text using +.
  • toStringAsFixed(n) = text with exactly n digits after the decimal point.

Between int and double

  • toInt() = cuts off the decimal part: 9.99.toInt() gives 9.
  • round() = rounds to the nearest whole number: 9.5.round() gives 10.
  • toDouble() = turns an int into a double: 9.toDouble() gives 9.0.

From double to int

void main() {
  double price = 99.75;
  print(price.toInt());
  print(price.round());
  print(price.floor());
  print(price.ceil());
}

Simple lesson: toString() turns values into text, and toInt() or round() turn decimals into whole numbers.

Type Casting

Type casting = telling Dart "treat this value as this type", with as.

dynamic value = 'Green Valley';
String school = value as String;

If you are wrong, the program crashes:

dynamic value = 'hello';
int number = value as int;

Real Dart stops with an error like type 'String' is not a subtype of type 'int' in type cast.

In this course's runner, as is not checked yet, so a wrong cast does not crash here.

Real Dart does check it. Never rely on a wrong cast.

Safe Casting Practices

Check with is first. Then Dart already knows the type, and you do not need as at all.

Check first, then use

void main() {
  dynamic value = 'green valley';
  if (value is String) {
    print(value.toUpperCase());
  }
  value = 42;
  if (value is int) {
    print(value + 8);
  }
}

Type promotion = after if (value is String), Dart treats value as a String inside that block.

Easy way to remember

  • Text to number: int.parse() if you are sure, int.tryParse() if a person typed it.
  • Number to text: toString().
  • Unsure of a type: check with is before you use it.

Simple lesson: prefer is checks over as casts, because a check cannot crash.

TL;DR

  1. A type says what kind of value a variable holds: int, double, num, String, bool.
  2. dynamic turns off checks, Object holds anything safely, and Null and Never are special.
  3. Type inference: var x = 5; makes x an int for good.
  4. Check: x is int, x.runtimeType. Cast: check with is, then use, or as when sure.
  5. Convert: int.parse, double.parse, tryParse for safety, toString(), toStringAsFixed().

Common mistakes

MistakeWrong ideaCorrect ideaWhat goes wrong
int age = '13';Quotes do not matterQuotes make textA value of type 'String' can't be assigned to a variable of type 'int'.
int price = 99.5;int can hold decimalsUse double for decimalsA value of type 'double' can't be assigned to a variable of type 'int'.
bool ok = 'true';'true' is a boolWrite true without quotesA type error.
True or TRUECase does not matterWrite true in small lettersUndefined name 'True'.
A phone number as intAll digits are numbersUse String when you never do maths on itLeading zeros are lost, and long numbers look odd.
dynamic everywheredynamic is easierUse real typesMistakes appear only while the program runs.
String name = null;Any variable can be emptyUse String? if it may be nullThe value 'null' can't be assigned.
Adding text numbers'85' + '90' is 175Parse first: int.parse('85')You get '8590'.
int.parse on user inputPeople always type digitsUse int.tryParse with ??A FormatException crash.
var x = 5; then x = 'five';var allows any typevar keeps the first typeA type error.
Joining a number to text with +'Total: ' + 92 worksUse $ or toString()A type error.
int.parse('9.5')parse handles decimalsUse double.parseA FormatException.
Casting without checkingas is always safeCheck with is firstA crash in real Dart.
toInt() to round9.99.toInt() is 10toInt() cuts, round() roundsYou get 9.

Check Yourself

Exercises

What to Remember

  • Every value has a type, and Dart checks it before the program runs.
  • Pick int for whole numbers, double for decimals, String for text and bool for yes/no.
  • var lets Dart infer the type, and the type stays fixed.
  • Use tryParse when text might not be a number.
  • Check with is before you cast.

Next: Operators. You will learn how to do maths, compare values and combine conditions.