Data Types Deep Dive
Data Types Deep Dive
Dart is a strongly-typed language, meaning every value has a type, and the compiler uses this information to ensure safety and prevent runtime crashes. In this lesson, we will explore both primitive and advanced types in Dart.
Primitive Data Types
Primitive types are the building blocks of data representation in Dart.
1. Numbers (int, double, num)
Dart represents numbers in three ways:
int: Integer values no larger than 64 bits. (e.g.,1,42,-10).double: 64-bit double-precision floating-point numbers. (e.g.,3.14,-0.5).num: A type that can hold either anintor adouble. Bothintanddoubleare subtypes ofnum.
dartvoid main() { int age = 25; double price = 19.99; num rating = 4.5; // Can be reassigned to an int rating = 5; // Valid }
2. Strings (String)
A String represents a sequence of characters. Dart strings are UTF-16 code units. You can use single or double quotes to declare strings.
dartvoid main() { String firstName = 'Alice'; String lastName = "Smith"; // String Interpolation String fullName = "$firstName $lastName"; print("Length: ${fullName.length}"); // Multi-line Strings using triple quotes String message = """ This is a multi-line string. """; // Raw Strings (prefixed with r, ignores escape characters) String path = r"C:\programfiles\dart"; }
3. Booleans (bool)
Booleans represent logical truth values: true and false. In Dart, only boolean objects can evaluate to true in condition checks (no JS-like "truthy" or "falsy" concepts for strings/numbers).
dartvoid main() { bool isPremium = true; if (isPremium) { print("Welcome VIP!"); } }
Special & Advanced Data Types
Dart provides several specialized types for scenarios where the compile-time type system is too restrictive or when representing absence of values.
1. dynamic
The dynamic type disables static type checking. A variable declared as dynamic can hold any value, and you can reassign it to values of completely different types.
[!WARNING]
Using dynamic removes type safety. Avoid it unless interacting with JSON or dynamic external APIs.
dartvoid main() { dynamic data = "Hello"; data = 42; // OK data = true; // OK }
2. Object
The Object class is the root class of the Dart class hierarchy, except for Null. Every non-null class in Dart inherits from Object. Unlike dynamic, Object still maintains static type checking.
dartvoid main() { Object obj = "Hello"; // obj.length; // Compile Error: The getter 'length' isn't defined for the class 'Object'. if (obj is String) { print(obj.length); // OK: Type promotion to String } }
3. Null
The Null type has exactly one value: null. It is used to represent the absence of a value. Under sound null safety, standard types cannot hold null unless explicitly declared as nullable.
dartvoid main() { String? nullableString = null; // OK because of '?' // String normalString = null; // Compile Error! }
4. Never
The Never type represents a type that can never be evaluated. It is used to indicate that a function will never return normally (e.g., it always throws an exception or loops indefinitely).
dartNever throwError() { throw Exception("An error occurred"); }
Type Checking and Casts
You can inspect and convert types at runtime using operators:
is: Returnstrueif the object has the specified type.is!: Returnstrueif the object does not have the specified type.as: Casts an object to a specific type.
dartvoid main() { num value = 10; if (value is int) { print("It's an integer!"); } // Explicit casting double doubleVal = value as double; // Throws TypeError if value is not double! }
Summary
- Use
intanddoublefor numeric calculations. - Use
Stringwith interpolation for formatting text. - Use
boolfor conditions. - Minimize the use of
dynamicto preserve type safety. - Leverage the
isoperator for runtime type validation.