in Dart, a typedef is used to create a type alias for a function signature.
It helps make code more readable, reusable, and type-safe, especially when you’re dealing with higher-order functions (functions that take other functions as parameters or return them).
In simple terms, typedef allows you to name a function type, so instead of writing complex function signatures everywhere, you can refer to it using a simple name.
Example 1: Basic Usage #
Without typedef:
void executeOperation(int a, int b, int Function(int, int) operation) {
print(operation(a, b));
}
int add(int x, int y) => x + y;
void main() {
executeOperation(5, 3, add);
}
With typedef:
typedef MathOperation = int Function(int, int);
void executeOperation(int a, int b, MathOperation operation) {
print(operation(a, b));
}
int add(int x, int y) => x + y;
void main() {
executeOperation(5, 3, add); // Output: 8
}
Here, MathOperation is a typedef that represents any function taking two int parameters and returning an int.
This makes the method signature cleaner and easier to understand, especially when passing multiple callbacks.
Example 2: Typedef with Callbacks (Practical Use) #
I used typedef in a Flutter app where I needed to handle API response callbacks:
typedef OnSuccess = void Function(String message);
typedef OnError = void Function(String error);
void fetchData(OnSuccess success, OnError error) {
try {
// Simulate API call
success("Data fetched successfully!");
} catch (e) {
error("Something went wrong");
}
}
void main() {
fetchData(
(msg) => print(msg),
(err) => print(err),
);
}
Here, typedef makes the function definition self-explanatory — anyone reading the code can easily understand that fetchData expects two callback functions: one for success and one for error.
Where I Applied It #
I applied typedefs in state management and networking layers.
For example, I had a typedef StateChangeHandler = void Function(AppState state);
This made it easier to pass around listeners or callbacks without rewriting the same function signatures everywhere.
Challenges Faced #
Initially, I found it tricky when typedefs were used for generic functions or when combined with Future types like typedef FutureCallback<T> = Future<T> Function();.
Also, when debugging, typedefs hide the underlying function signature — so I had to refer back to their definition often.
Limitations #
- Typedefs in Dart don’t allow you to create new types — they are just aliases.
- You can’t overload typedefs with different parameter lists.
- Older Dart versions treated typedefs differently (but now, function types are fully supported as first-class citizens).
- Alternative
If the function signature is simple or used only once, we can use inline function types directly:
void performAction(String Function(String) callback) {
print(callback('Hello'));
}
But when the same signature is reused in multiple places, typedef makes it cleaner and consistent.
So in short:
A typedef in Dart is a way to define a custom name for a function type, improving readability and reducing redundancy — especially useful when passing callbacks or higher-order functions.
