Skip to main content
Annotations are syntactic metadata that associate compile-time constant values with code declarations. They provide structured information to the compiler, static analyzer, or runtime environment without altering the execution logic of the code itself. Syntactically, an annotation is an expression beginning with the @ symbol that evaluates to a compile-time constant.

Syntax and Placement

Annotations are placed immediately preceding the declaration they modify, such as a library, class, function, variable, or parameter. The syntax varies depending on whether the annotation is a reference to a constant variable or an invocation of a constant constructor. 1. Constant Variable Reference If the annotation is a defined constant variable, parentheses are omitted.
const myTag = 'internal_use';

@myTag
class MyClass {}
2. Constant Constructor Invocation If the annotation is an instance created via a constant constructor, parentheses are required (even if there are no arguments).
class Metadata {
  const Metadata();
}

@Metadata() // Parentheses required for constructor invocation
void myMethod() {}
3. Named Constructor Invocation If the annotation class uses a named constructor, the syntax includes the constructor name.
@Todo.urgent()
void fixThis() {}

Defining Custom Annotations

Any object that is a compile-time constant can serve as an annotation. There are two primary ways to define them:

Class-Based Annotations

The most common approach is to define a class with a const constructor. This allows the annotation to accept parameters and structure data.
// 1. Define the class
class Refactor {
  final String message;
  final int priority;

  // 2. Define a const constructor
  const Refactor(this.message, {this.priority = 1});
}

// 3. Apply the annotation
@Refactor('Optimize for performance', priority: 5)
void complexAlgorithm() {
  // ...
}

Constant Variable Annotations

You can also define a top-level constant variable (such as a string, number, or boolean) and use it directly as an annotation.
// 1. Define a constant variable
const experimental = 'experimental_feature';

// 2. Apply the annotation
@experimental
class BetaFeature {}

Parameter Constraints

Because annotations are evaluated at compile-time, arguments passed to an annotation constructor must be compile-time constants. Valid arguments include:
  • Literals (numbers, strings, booleans, null).
  • Const lists, sets, or maps.
  • References to other constant variables.
  • Invocations of other constant constructors.
const String globalTag = 'v1.0';

class Tag {
  final String value;
  final List<int> codes;
  const Tag(this.value, this.codes);
}

// Valid
@Tag(globalTag, [10, 20]) 
class ValidTarget {}

// Invalid: DateTime.now() is not a compile-time constant
// @Tag('timestamp', [DateTime.now().millisecondsSinceEpoch]) 
class InvalidTarget {}

Restricting Targets

By default, an annotation can be applied to any declaration. To restrict an annotation to specific code elements (e.g., only classes or only parameters), apply the @Target meta-annotation from package:meta.
import 'package:meta/meta_meta.dart';

@Target({TargetKind.parameter})
class RequiredParam {
  const RequiredParam();
}

void connect(
  @RequiredParam() String host, // Valid
  int port,
) {}

// @RequiredParam() // Compilation Error: Annotation not valid on class
class Connection {}

Processing Mechanisms

Dart annotations do not have inherent executable behavior; they are passive data. They are utilized through two primary mechanisms:
  1. Static Analysis: Tools like the Dart analyzer read annotations to enforce rules (e.g., @override, @deprecated).
  2. Code Generation/Reflection:
    • Compile-time: Build systems (using package:source_gen and package:build_runner) scan source code for specific annotations to generate additional files (e.g., JSON serialization logic).
    • Runtime: Reflection (via dart:mirrors, though generally discouraged or unavailable in Flutter/Web) allows introspection of metadata during execution.
Master Dart with Deep Grasping Methodology!Learn More