| |

Dart 4 🎯 Built-in Data Types: int, double, num, String, bool

Dart’s type system is built on a small set of core types. The previous chapters covered how variables are declared and how the runtime executes code. This chapter covers the values those variables hold. Dart’s built-in types are not just labels — they are classes with methods, operators, and a defined place in the type hierarchy. Understanding them is the foundation for writing type-safe code that the compiler can verify and the runtime can optimize.

Key point: Dart’s numeric types are int for integers and double for floating-point numbers. The num type is the superclass of both. Dart does not implicitly convert between int and double at runtime — the only exception is integer literals, which the compiler can reinterpret as double when the context requires it. A String is an immutable sequence of UTF-16 code units. A bool is either true or false, and Dart does not treat any other value as a “truthy” or “falsy” boolean.


Why the Built-in Types Matter

Every Dart program is built from these types. They appear in every function signature, every variable declaration, and every collection. Getting them wrong leads to type errors that the compiler catches, but understanding them deeply leads to code that is faster, safer, and more idiomatic.

The numeric problem. Dart has two numeric types, not one. An int is a whole number. A double is a floating-point number. They are not interchangeable at runtime, even though an integer literal like 1 can be assigned to a double variable. This distinction matters when you parse data from an API or a database, where a value might come back as an int when you expected a double .

The string problem. A String in Dart is immutable. Every operation that “modifies” a string actually returns a new string. This is different from languages where strings are mutable character arrays. Understanding immutability explains why string concatenation in a loop is slow and why StringBuffer exists.

The boolean problem. Dart does not have “truthy” and “falsy” values. if (1) is a compile-time error. You must write if (value != 0). This strictness prevents a class of bugs where a value that happens to be zero or empty is treated as false when it should not be .

The trade-off. Dart’s type system is strict, but it is not rigid. The num type provides flexibility when a value could be either an int or a double. Type inference reduces the need for explicit annotations. The balance is intentional: enough flexibility to be practical, enough strictness to catch real errors.


a. Numbers: int, double, and num

Dart numbers come in two flavors: int and double. The int type represents integer values. On native platforms, int is a 64-bit signed integer with a range from -2^63 to 2^63 – 1. On the web, integer values are represented as JavaScript numbers and are limited to the range -2^53 to 2^53 – 1 .

var x = 1;          // inferred as int
var y = 1.1;        // inferred as double
var exponents = 1.42e5;  // scientific notation, inferred as double

The double type represents 64-bit double-precision floating-point numbers, as specified by the IEEE 754 standard . A number with a decimal point is a double. Scientific notation also produces a double.

The num type is the superclass of both int and double. A variable declared as num can hold either type .

num x = 1;        // x holds an int
x += 2.5;         // x now holds a double

The num type includes the basic operators: +, -, /, *. It is also where you find methods like abs(), ceil(), and floor(). Bitwise operators like >> are defined only on int .

The int-to-double conversion rule. Dart does not implicitly coerce int to double at runtime. The only exception is the integer literal. When the static context type of an integer literal is double, the compiler reinterprets the literal as a double .

double z = 1;     // ✅ Valid: 1 is reinterpreted as 1.0

This works because of a specific rule in the language specification: “Let l be an integer literal… If double is assignable to T and int is not assignable to T, then the static type of l is double” . The literal is not being converted — it is being interpreted as a double because the context requires it.

The rule does not apply to variables. If you have an int variable and assign it to a double variable, you get a compile-time error.

int a = 1;
double b = a;     // ❌ Error: int is not a subtype of double

The fix is to call toDouble() explicitly.

double b = a.toDouble();  // ✅ Valid

Number literals as compile-time constants. Number literals are compile-time constants. Many arithmetic expressions are also compile-time constants, as long as their operands are compile-time constants that evaluate to numbers .

const msPerSecond = 1000;
const secondsUntilRetry = 5;
const msUntilRetry = secondsUntilRetry * msPerSecond;  // ✅ 5000

Digit separators. Dart allows underscores as digit separators in numeric literals. This improves readability for large numbers .

var million = 1_000_000;
var creditCard = 1234_5678_9012_3456;

b. Strings: Immutable Sequences of UTF-16 Code Units

A String in Dart is an immutable sequence of UTF-16 code units . You can create a string with single quotes, double quotes, or triple quotes for multi-line strings.

var s1 = 'Single quotes work well.';
var s2 = "Double quotes work just as well.";
var s3 = 'It\'s easy to escape.';
var s4 = "It's even easier with double quotes.";

There is no difference between single and double quotes. Choose one and be consistent. The choice is a matter of style, not semantics.

String interpolation. You can embed an expression inside a string with ${expression}. If the expression is an identifier, you can omit the braces and write $identifier .

var name = 'Alice';
var greeting = 'Hello, $name!';                    // Hello, Alice!
var upper = 'Hello, ${name.toUpperCase()}!';       // Hello, ALICE!

The compiler translates $name into name.toString() and ${name.toUpperCase()} into the result of the method call, followed by .toString() if the result is not already a string .

String concatenation. You can concatenate adjacent string literals or use the + operator.

var s1 = 'String ' 'concatenation';               // adjacent literals
var s2 = 'The + operator ' + 'works, as well.';   // + operator

Adjacent string literals are concatenated at compile time. The + operator is evaluated at runtime. For simple concatenation, adjacent literals are preferred because they are free.

Multi-line strings. Triple quotes create multi-line strings.

var s1 = '''
You can create
multi-line strings.
''';

var s2 = """This is also a
multi-line string.""";

Raw strings. A raw string, prefixed with r, does not process escape sequences.

var s = r'In a raw string, \n is two characters.';

In a raw string, \n is a backslash followed by an n, not a newline character. This is useful for regular expressions and file paths.

String immutability. A String is immutable. Methods like toUpperCase(), substring(), and replaceAll() return new strings. They do not modify the original.

var s = 'hello';
var upper = s.toUpperCase();
print(s);        // hello
print(upper);    // HELLO

String literals as compile-time constants. String literals are compile-time constants if any interpolated expression is a compile-time constant that evaluates to a null, numeric, string, or boolean value .

const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

const validConstString = '$aConstNum $aConstBool $aConstString';

// const invalidConstString = '$aNum $aBool $aString $aConstList';
// aNum is not const, so invalidConstString is not a valid const

c. Booleans: True or False, Nothing Else

Dart has a type named bool. Only two objects have type bool: the boolean literals true and false, which are both compile-time constants .

bool isActive = true;
bool isCompleted = false;

Dart is type-safe. You cannot use a non-boolean value in a boolean context. Unlike JavaScript, Dart does not treat 0, '', null, or any other value as “falsy” .

int value = 1;

// This is a compile-time error:
// if (value) { print('Valid'); }

// The correct way:
if (value != 0) {
    print('Value is non-zero');
}

The compiler requires an explicit boolean expression. This prevents a large class of bugs where a value that happens to be zero or empty is treated as false when the programmer intended something else.

Boolean operators. Dart provides three logical operators: && (AND), || (OR), and ! (NOT). These operators follow standard truth tables .

bool a = true;
bool b = false;

print(a && b);   // false
print(a || b);   // true
print(!a);       // false

Dart uses short-circuit evaluation. In a && b, if a is false, b is not evaluated. In a || b, if a is true, b is not evaluated .

bool result = true || (throw Exception('Not evaluated'));
// result is true, the exception is never thrown

Boolean values from comparisons. Comparison operators like ==, !=, >, <, >=, and <= produce boolean values .

int age = 25;
bool isAdult = age >= 18;
bool canVote = isAdult && age >= 21;

Equality. The == operator tests whether two objects are equal. For strings, it compares the sequence of UTF-16 code units .

const guess = 'dog';
const guessEqualsCat = guess == 'cat';  // false

The bool type is sealed. You cannot create a bool value other than true and false. You cannot subclass bool. The type is final and the literals are the only instances.


Complete Example Session

This session demonstrates the built-in types in a single Dart file.

void main() {
    // Numbers
    int meaningOfLife = 42;
    double valueOfPi = 3.141592;
    num flexible = 42;
    flexible += 2.5;

    print('meaningOfLife: $meaningOfLife (${meaningOfLife.runtimeType})');
    print('valueOfPi: $valueOfPi (${valueOfPi.runtimeType})');
    print('flexible: $flexible (${flexible.runtimeType})');

    // Integer literal reinterpreted as double
    double z = 1;
    print('z: $z (${z.runtimeType})');

    // Explicit conversion
    int a = 1;
    double b = a.toDouble();
    print('b: $b (${b.runtimeType})');

    // Strings
    String name = 'Alice';
    String greeting = 'Hello, $name!';
    String raw = r'Raw string: \n is two characters';
    String multi = '''
    Multi-line
    string''';

    print(greeting);
    print(raw);
    print(multi);

    // String interpolation with expression
    print('Uppercase: ${name.toUpperCase()}');

    // Booleans
    bool isActive = true;
    bool isCompleted = false;
    bool isAdult = 25 >= 18;
    bool canVote = isAdult && 25 >= 21;

    print('isActive: $isActive');
    print('isCompleted: $isCompleted');
    print('isAdult: $isAdult');
    print('canVote: $canVote');

    // Short-circuit evaluation
    bool shortCircuit = true || (throw Exception('Not evaluated'));
    print('shortCircuit: $shortCircuit');

    // Boolean in condition
    if (isAdult) {
        print('Access granted');
    }
}

Quick Reference

The Numeric Types

TypeDescriptionRange (Native)
intWhole numbers-2^63 to 2^63 – 1
double64-bit floating pointIEEE 754
numSuperclass of int and doubleEither

The String Features

FeatureSyntaxExample
Single quotes'...''hello'
Double quotes"...""hello"
Interpolation$name or ${expr}'Hello, $name'
ConcatenationAdjacent or +'a' 'b'
Multi-line'''...''''''line1\nline2'''
Raw stringr'...'r'\n'

The Boolean Operators

OperatorNameExample
&&ANDa && b
||ORa || b
!NOT!a
==Equalitya == b
!=Inequalitya != b

The Numeric Conversion Rules

FromToRule
Integer literaldoubleReinterpreted if context requires
int variabledoubleRequires explicit toDouble()
double variableintRequires explicit toInt()

Best Practices

✅ Do This:

// Use int for whole numbers
int count = 42;                                                  // ✅
// Use double for decimal numbers
double price = 19.99;                                            // ✅
// Use string interpolation
var greeting = 'Hello, $name!';                                  // ✅
// Use raw strings for regex and paths
var pattern = r'\d+';                                            // ✅
// Use explicit boolean expressions
if (value != 0) { ... }                                          // ✅

❌ Don’t Do This:

// Don't rely on implicit int-to-double conversion at runtime
int a = 1;
double b = a;  // ❌ Compile-time error
// Don't use truthy/falsy values
if (1) { ... }  // ❌ Compile-time error
// Don't concatenate strings in a loop with +
var result = '';
for (var i = 0; i < 1000; i++) {
    result += '$i';  // ⚠️ Slow — use StringBuffer
}
// Don't assume strings are mutable
var s = 'hello';
s.toUpperCase();  // ⚠️ Returns a new string, does not modify s

Common Pitfalls

PitfallWhy It HappensFix
int not a subtype of doubleDart does not coerce at runtimeUse toDouble()
String not modifiedStrings are immutableAssign the result
if (value) errorDart requires explicit booleanUse value != 0
Raw string escape failsr prefix disables escapesRemove r for escape sequences
Compile-time const failsInterpolated expression not constUse only const values

Real-World Examples

1. Integer

int count = 42;

2. Double

double pi = 3.14159;

3. Num

num value = 42;
value += 0.5;

4. Integer Literal as Double

double z = 1;

5. String Interpolation

var message = 'Hello, $name!';

6. String Concatenation

var full = 'Hello, ' + 'world!';

7. Multi-line String

var text = '''
Line 1
Line 2
''';

8. Raw String

var path = r'C:\Users\name';

9. Boolean from Comparison

bool isAdult = age >= 18;

10. Boolean Logic

bool canAccess = isLoggedIn && hasPermission;

Visual

The Numeric Type Hierarchy

┌──────────────────────────────────────────────┐
│  num                                         │
│    ├─ int     (whole numbers)                │
│    └─ double  (floating point)               │
│                                              │
│  int and double are not interchangeable      │
│  at runtime without explicit conversion.     │
│                                              │
└──────────────────────────────────────────────┘

String Immutability

┌──────────────────────────────────────────────┐
│  var s = 'hello';                            │
│       │                                      │
│       ▼                                      │
│  s.toUpperCase() → 'HELLO' (new string)      │
│       │                                      │
│       ▼                                      │
│  s is still 'hello'                          │
│                                              │
│  Every "modifying" method returns a new      │
│  string. The original is never changed.      │
│                                              │
└──────────────────────────────────────────────┘

Boolean Strictness

┌──────────────────────────────────────────────┐
│  JavaScript:                                 │
│    if (0) { }      → false                   │
│    if ('') { }     → false                   │
│    if (null) { }   → false                   │
│                                              │
│  Dart:                                       │
│    if (0) { }      → ❌ Compile error        │
│    if ('') { }     → ❌ Compile error        │
│    if (null) { }   → ❌ Compile error        │
│                                              │
│  Use explicit comparisons.                   │
│                                              │
└──────────────────────────────────────────────┘

The Integer Literal Rule

┌──────────────────────────────────────────────┐
│  double z = 1;    → ✅ 1 is interpreted as   │
│                       1.0 because double     │
│                       is assignable and int  │
│                       is not                 │
│                                              │
│  int a = 1;                                  │
│  double b = a;    → ❌ int is not a subtype  │
│                       of double              │
│                                              │
│  double b = a.toDouble(); → ✅ Explicit      │
│                                              │
└──────────────────────────────────────────────┘

Summary

ItemValue
Integer typeint
Floating-point typedouble
Superclassnum
String typeString (immutable)
Boolean typebool (true or false)
String interpolation$name or ${expression}
Raw stringr'...'
Multi-line string'''...'''
Boolean operators&&, `
Truthy/falsyNot supported

Key takeaways:

  • Dart has two numeric types: int and double. The num type is the superclass of both. An integer literal can be reinterpreted as a double when the context requires it, but an int variable cannot be implicitly converted to a double at runtime .
  • Strings are immutable sequences of UTF-16 code units. Methods like toUpperCase() and substring() return new strings. Use StringBuffer for efficient concatenation in loops .
  • String interpolation embeds expressions in strings. Use $identifier for simple identifiers and ${expression} for complex expressions. The compiler translates the interpolation into toString() calls .
  • Dart does not have truthy or falsy values. if (value) is a compile-time error unless value is a bool. Use explicit comparisons like value != 0 or value != null .
  • Boolean operators use short-circuit evaluation. In a && b, b is not evaluated if a is false. In a || b, b is not evaluated if a is true .
  • Raw strings disable escape sequences. A raw string prefixed with r treats \n as two characters, not a newline. This is useful for regular expressions and file paths .
  • String literals can be compile-time constants. A string literal is a compile-time constant if any interpolated expression is a compile-time constant that evaluates to null, a number, a string, or a boolean .

Remember: Dart’s built-in types are strict but practical. int and double are separate types with an explicit conversion rule. Strings are immutable and support interpolation. Booleans are strictly boolean. The type system catches errors at compile time that would become runtime bugs in looser languages. Understanding the rules — especially the integer literal reinterpretation and the immutability of strings — prevents the most common mistakes.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!