Dart - Pass a Function as a Parameter

This tutorial shows you how to pass a function as a parameter of another function in Dart.

Just like most other programming languages, Dart allows us to create functions. A function can have 0 to n parameters with various types. Sometimes, there are cases where you want to pass a function as a parameter of another function. Below are several ways to do it.

Pass Any Function

For example, you have a function for printing a list of values. The list of values is obtained from a passed function. So, the function must have a parameter that accepts a function. In addition, it needs to invoke the passed function to execute it and obtain the return value.

The parameter type must be a Function. Below is the most basic example of how to define such a parameter. To invoke the passed function, just call it by using (), just like a normal function call. You can put some arguments between the brackets if there is any.

  void printValues(Function dataGenerator) {
    var values = dataGenerator(10);
    print('THE VALUES are $values');
  }

Pass a Function with Specific Parameters and Return Type

In the example above, the passed function can have any number of parameters. The type of the parameters are not restricted. Besides that, the return value of the function can be any type. The downside is if you try to invoke the passed function using the wrong parameters or incorrectly cast the return value, it may result in a runtime error.

If you need to restrict the number and types of the parameters, you can define the parameter types inside a () (bracket) after the Function keyword. Each parameter type is separated by a comma. By doing that, the passed function must comply with the number of parameters including the types. If there are no parameters between the brackets, the passed function must not have any parameters.

To restrict the return type, you can define it before the Function keyword. If it's not defined, the return type will be dynamic. If there is no return value, it can be written as void.

In the example below, we restrict that the function passed as the argument must have a parameter whose type is int. Furthermore, it has to return List<int>. If you try to pass an incompatible function, the compiler will give you an error.

  void printValues(List<int> Function(int) dataGenerator) {
    List<int> values = dataGenerator(10);
    print('THE VALUES are $values');
  }
  
  List<int> generateValues(n) {
    return List<int>.generate(n, (i) => i + 1);
  }
  
  main() {
    printValues(generateValues);
  }

To improve readability, it's also allowed to add a name after the parameter type.

  void printValues(List<int> Function(int n) dataGenerator) {
    List<int> values = dataGenerator(10);
    print(values);
  }

While the examples above pass a function that's already defined, it's also possible to directly create and pass the function.

  printValues((n) {
    return List<int>.generate(n, (i) => i + 1);
  });

Using typedef as Parameter Type

Dart allows you to define a type by using the typedef keyword. Instead of writing the function's return type and parameters which can be quite long, you can make it shorter by defining the parameter type using typedef.

For example, the type of the parameter in the previous example can be defined as.

  typedef DataGenerator = List<int> Function(int);

Then, you can use the defined type as the paramater type.

  void printValues(DataGenerator dataGenerator) {
    List values = dataGenerator(10);
    print('THE VALUES are $values');
  }

Summary

Dart allows us to pass a function as a parameter by defining the parameter type as Function. The parameters and the return value can be restricted if necessary. In addition, you can use typedef to define the function type.

You can also read about: