What is the difference between required, optional, and named parameters in Dart?
#dart#functions#parameters#required#named#optional
Answer
Overview
Dart functions support four types of parameters:
- Required Positional — Must be provided, order matters
- Optional Positional — Can be omitted, wrapped in text
[] - Named Parameters — Referenced by name, wrapped in text
{} - Required Named — Named but mandatory, uses keywordtext
required
1. Required Positional Parameters
These must always be provided in the exact order they are defined.
dart// Both parameters are required and positional String greet(String name, int age) { return 'Hello $name, you are $age years old'; } greet('Alice', 30); // ✅ Works // greet('Alice'); // ❌ Error: missing argument // greet(30, 'Alice'); // ❌ Error: wrong types (order matters)
2. Optional Positional Parameters text[]
text
[]Wrapped in square brackets. Can be omitted — defaults to
text
nulldartString greet(String name, [int? age, String title = 'Mr.']) { if (age != null) { return 'Hello $title $name, age $age'; } return 'Hello $title $name'; } greet('Alice'); // ✅ 'Hello Mr. Alice' greet('Alice', 30); // ✅ 'Hello Mr. Alice, age 30' greet('Alice', 30, 'Dr.'); // ✅ 'Hello Dr. Alice, age 30' // greet('Alice', 'Dr.'); // ❌ Can't skip age (positional order)
3. Named Parameters text{}
text
{}Wrapped in curly braces. Referenced by name, so order doesn't matter. Optional by default.
dartString greet({String? name, int? age, String title = 'Mr.'}) { return 'Hello $title ${name ?? "Guest"}, age ${age ?? "unknown"}'; } greet(); // ✅ 'Hello Mr. Guest, age unknown' greet(name: 'Alice'); // ✅ 'Hello Mr. Alice, age unknown' greet(age: 30, name: 'Alice'); // ✅ Order doesn't matter greet(title: 'Dr.', name: 'Alice'); // ✅ Skip age entirely
4. Required Named Parameters
Use the
text
requireddartclass User { final String name; final String email; final int? age; // name and email are required, age is optional User({ required this.name, required this.email, this.age, }); } User(name: 'Alice', email: 'alice@mail.com'); // ✅ User(name: 'Alice', email: 'alice@mail.com', age: 30); // ✅ // User(name: 'Alice'); // ❌ Error: 'email' is required
Mixing Parameters
You can mix required positional with either named OR optional positional (but not both).
dart// ✅ Required positional + Named parameters void sendEmail(String to, {String? subject, required String body}) { print('To: $to, Subject: $subject, Body: $body'); } sendEmail('alice@mail.com', body: 'Hello!', subject: 'Greetings'); // ✅ Required positional + Optional positional void log(String message, [String level = 'INFO', DateTime? timestamp]) { print('[$level] $message at ${timestamp ?? DateTime.now()}'); } log('Server started'); log('Error occurred', 'ERROR'); // ❌ Cannot mix optional positional [] and named {} in same function // void invalid(String a, [int? b], {String? c}) {} // Compile error!
Key Differences
| Feature | Required Positional | Optional Positional text | Named text | Required Named |
|---|---|---|---|---|
| Syntax | text | text | text | text |
| Must provide | Yes | No | No | Yes |
| Order matters | Yes | Yes | No | No |
| Default value | Not applicable | Yes ( text | Yes ( text | Not applicable |
| Nullable | Only if text | Usually text | Usually text | Can be non-null |
| Caller clarity | Low (just values) | Low | High (named) | High (named) |
Best Practices
dart// ✅ Use required named for constructors (Flutter convention) class CustomButton extends StatelessWidget { const CustomButton({ super.key, required this.label, required this.onPressed, this.color = Colors.blue, // Optional named with default }); final String label; final VoidCallback onPressed; final Color color; } // ✅ Use positional for simple functions with 1-2 params int add(int a, int b) => a + b; // ✅ Use named params when function has 3+ parameters void configureApp({ required String appName, required String apiUrl, bool debugMode = false, Duration timeout = const Duration(seconds: 30), }) { } // ✅ Use optional positional for convenience overloads void log(String message, [String? tag]) { print('[${tag ?? 'APP'}] $message'); }
Key Insight: Flutter's widget constructors almost exclusively use required named parameters for clarity. Positional parameters are preferred for simple utility functions with 1-2 arguments.