Skip to main content
void is a special type in the Dart type system indicating that a value is never intended to be used. It serves as a static analysis marker to prevent the accidental consumption of results from functions that perform side effects without returning a meaningful value.

Type Semantics

In Dart’s sound type system, void behaves with specific constraints regarding assignment and usage:
  • Producer Side (Input): void functions as a supertype. An object of any type can be assigned to a reference of type void (effectively discarding the value).
  • Consumer Side (Output): The static analyzer prohibits the usage of a value typed as void. You cannot access properties, call methods, or pass a void value to a function expecting a non-void type.
  • Runtime Representation: At runtime, a function declared as returning void implicitly returns null if no return statement is provided. However, the type system prevents code from relying on this null value.

Syntax and Declaration

void is primarily used as a return type for functions, methods, and setters, or as a generic type argument.
// Function declaration
void performAction() {
  print('Action performed');
  // Implicitly returns null, but statically typed as void
}

// Generic type argument
final Future<void> computation = Future.delayed(const Duration(seconds: 1));

Assignment Constraints

The analyzer enforces strict rules on how void expressions can be assigned. Unlike null, a value of type void cannot be assigned to dynamic or Object?. It can only be assigned to a reference of type void.
void doSomething() {}

void main() {
  // Allowed: Assigning to void (discarding the result)
  void a = doSomething();

  // Compile-time Error: Cannot assign void to dynamic
  dynamic b = doSomething();

  // Compile-time Error: Cannot assign void to Object?
  Object? c = doSomething(); 

  // Compile-time Error: Cannot assign void to concrete types
  int d = doSomething(); 
}

Return Syntax and Generalized Void

Dart distinguishes between block syntax and arrow syntax regarding void return values.

Block Syntax

When using a block body ({ ... }), a void function cannot explicitly return a non-null value.
void strictReturn() {
  return;      // Allowed
  return null; // Allowed
  return 10;   // Compile-time Error: Can't return a value from a void function.
}

Arrow Syntax (Generalized Void)

When using arrow syntax (=>), Dart permits a void function to return a value of any type. This is known as “generalized void.” The returned value is evaluated but immediately discarded by the type system. This allows for shorthand forwarding of function calls without changing the return type signature.
int calculate() => 42;

// Allowed: The integer result from calculate() is discarded.
void fireAndForget() => calculate(); 

// Allowed: Explicitly returning a value is permitted in arrow syntax.
void discardValue() => 100; 

Generics and Nullability

void is distinct from null in generic contexts, signaling intent to the analyzer.
  • Future<void>: The future completes, but the consumer should ignore the result.
  • Future<null>: The future completes and explicitly yields the value null.
While functionally similar at runtime (both complete with null), Future<void> enforces stricter static analysis rules on the then callback, preventing the argument from being used.
Master Dart with Deep Grasping Methodology!Learn More