Skip to main content
The * (asterisk) in Dart functions primarily as a binary infix operator for multiplicative operations, and lexically as a suffix modifier for generator functions and yield delegation.

The Binary Operator (*)

As an operator, * is a syntactic sugar for a method call on the left operand. It possesses multiplicative precedence (level 14 in Dart’s precedence table), meaning it evaluates after unary operators but before additive operators, with left-to-right associativity.

Built-in Implementations

1. Numeric Multiplication When applied to num types (int or double), it performs standard arithmetic multiplication. The return type is determined by the operands: if both are int, it returns an int; if either is a double, it returns a double.
int a = 5 * 2;       // Evaluates to 10
double b = 5.0 * 2;  // Evaluates to 10.0
2. String Repetition Dart’s String class implements the * operator, accepting an int as the right operand. It returns a new string containing the original string repeated the specified number of times.
String repeated = 'Dart' * 3; // Evaluates to 'DartDartDart'

Operator Overloading

Because * is implemented as an instance method, it can be overridden in user-defined classes using the operator keyword. The right operand can be of any type specified by the method signature.
class Matrix {
  final List<int> values;
  Matrix(this.values);

  // Overloading the * operator
  Matrix operator *(int scalar) {
    return Matrix(values.map((v) => v * scalar).toList());
  }
}

Matrix m1 = Matrix([1, 2, 3]);
Matrix m2 = m1 * 2; 

Lexical Modifiers (Generators)

Beyond binary operations, the * symbol is a structural component of Dart’s generator syntax. It modifies the behavior of functions and the yield keyword. 1. sync* and async* Appending * to the sync or async keywords transforms a standard function into a generator function.
  • sync* forces the function to return an Iterable<T> and evaluates synchronously.
  • async* forces the function to return a Stream<T> and evaluates asynchronously.
Iterable<int> synchronousGenerator() sync* {
  yield 1;
}

Stream<int> asynchronousGenerator() async* {
  yield 1;
}
2. yield* (Yield Delegation) When appended to the yield keyword, * delegates the emission of values to another Iterable or Stream. Instead of emitting the collection as a single object, yield* flattens the sequence, emitting each element of the delegated collection individually into the current generator’s output.
Iterable<int> delegatedGenerator() sync* {
  yield* synchronousGenerator(); 
}
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More