Skip to main content
void is a special type in Dart used to indicate that the value of an expression is completely discarded and cannot be used. It serves as a static type system constraint rather than a distinct runtime type, signaling to the compiler that a function’s return value or a generic type argument is intentionally meaningless.

Type System Behavior

In Dart’s sound type system, void is not a bottom type or a completely empty type. At runtime, void is equivalent to Object? (meaning it can technically hold any value, including null). However, at compile-time, the Dart analyzer strips away all access to the object’s interface.
  • Property/Method Access: You cannot call methods or access properties on an expression of type void.
  • Assignment: You cannot assign a void expression to a variable, unless that variable is explicitly typed as void. Attempting to assign a void expression to dynamic, var, or any other type results in a compile-time error.
void doSomething() {}

void main() {
  // Static Error: This expression has type 'void' and can't be used.
  var result = doSomething(); 
  
  // Static Error: This expression has type 'void' and can't be used.
  dynamic dynResult = doSomething();
  
  // Allowed, but strictly limits further use of 'explicitVoid'
  void explicitVoid = doSomething(); 
}

Return Semantics

When a function is declared with a void return type, Dart enforces specific rules depending on whether the function uses a block body ({ ... }) or an arrow body (=>).

Block-Bodied Functions

In a block-bodied void function, returning a concrete value or explicitly returning null violates Dart’s strict return rules and results in a compile-time error.
  1. Implicit Return: If no return statement is provided, the function implicitly returns null at runtime.
  2. Empty Return: An empty return; statement is valid and halts execution.
  3. Returning Void: You can return the result of another void expression.
  4. Strict Errors: Explicitly returning null (return null;) or any concrete value (return 5;) is a static compilation error.
void emptyReturn() {
  return; // Valid
}

void chainedVoid() {
  return emptyReturn(); // Valid: returning another void expression
}

void invalidNullReturn() {
  return null; // Static Error: A value of type 'Null' can't be returned from a void function.
}

void invalidValueReturn() {
  return "string"; // Static Error: A value of type 'String' can't be returned from a void function.
}

Arrow Functions (=>)

Unlike block-bodied functions, an arrow function with a void return type can evaluate an expression that results in a concrete value. The Dart compiler permits this syntax and implicitly discards the resulting value. This semantic exception exists primarily to facilitate concise callback implementations.
int calculateValue() => 42;

// Valid: The integer result of calculateValue() is evaluated but statically discarded.
void arrowVoid() => calculateValue();

// Valid: Evaluates to 5, but the value is discarded by the compiler.
void inlineArrow() => 5;

Generics and Parameterized Types

void is frequently used as a type argument in generics to satisfy type signatures where a parameterized type is required, but the inner value must be ignored. The compiler enforces the same strict access rules on the generic type parameter.
// The Future completes, but its resolved value cannot be utilized.
Future<void> asyncOperation() async {
  await Future.delayed(Duration(seconds: 1));
}

// A generic class instantiated with void
class Box<T> {
  T? value;
  Box(this.value);
}

void genericExample() {
  Box<void> voidBox = Box<void>(null);
  
  // Static Error: This expression has type 'void' and can't be used.
  print(voidBox.value.toString()); 
}

void vs Null

While a void function implicitly returns null at runtime, void and Null are distinct in the static type system. A variable of type Null can only ever hold the value null, but its value can be evaluated, assigned, and passed around. A void expression’s value, regardless of what it is at runtime, is statically forbidden from being evaluated or consumed by the surrounding code.
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More