Skip to main content
dynamic is a special static type in Dart that explicitly disables static type checking for the associated variable. It indicates to the compiler that the type of the underlying value is not known until runtime, permitting the assignment of any value and the invocation of any member without compile-time validation.

Static Analysis Behavior

When a variable is declared as dynamic, the Dart analyzer suspends type enforcement. Unlike standard types, which enforce a specific interface, dynamic assumes that any method call or property access is valid.
  • Assignment: A variable of type dynamic can be assigned a value of any type (e.g., int, String, List, or custom classes).
  • Reassignment: The type of value held by the variable can change during execution.
  • Member Access: The compiler permits calls to any method or getter/setter on the variable.

Syntax and Mechanics

void main() {
  // Declaration
  dynamic value = "A string";

  // Reassignment to a different type is permitted
  value = 42; 
  value = [1, 2, 3];

  // Member invocation bypasses static analysis
  // The compiler allows this even if 'nonExistentMethod' is not defined on List
  value.nonExistentMethod(); 
}

Runtime Dispatch

While dynamic bypasses compile-time checks, type safety is enforced at runtime. When a member is invoked on a dynamic variable, the Dart runtime performs a dynamic dispatch:
  1. The runtime inspects the actual class of the object currently held by the variable.
  2. It attempts to locate the requested member on that class.
  3. If the member exists, execution proceeds.
  4. If the member does not exist, the runtime throws a NoSuchMethodError.

Distinction from Object?

Although both dynamic and Object? can accept any value (including null), they differ fundamentally in how the compiler treats member access:
  • Object?: The root of the entire Dart type hierarchy. Every type in Dart is a subtype of Object?. The compiler enforces strict type checking, permitting only operations defined on the Object class (e.g., toString, hashCode, ==). To access members specific to the underlying type, explicit type casting or type checks are required.
  • dynamic: Permits all operations. It effectively turns off the safety guarantees of the type system for that specific variable, allowing any member access without casting.
void comparison(Object? obj, dynamic dyn) {
  // Object? restricts operations to those defined on Object
  // obj.length; // Compile-time Error: 'length' is not defined for 'Object?'.
  
  // dynamic permits operations
  dyn.length;   // Allowed by compiler. Throws at runtime if the value has no .length.
}

Type Inference Fallback

If a variable is declared without an explicit type and the analyzer cannot infer a specific type from the context or initialization, Dart implicitly assigns the type dynamic.
// 'x' is inferred as dynamic because no type or initial value is provided
var x; 
x = 10;
x = "string";
Master Dart with Deep Grasping Methodology!Learn More