Symbol in Dart is an opaque, immutable object representing an operator or identifier declared in a Dart program. Symbols serve as canonicalized keys used primarily in APIs that refer to identifiers by name, such as noSuchMethod or the dart:mirrors reflection library.
Syntax and Instantiation
Symbols are created via the symbol literal syntax or the class constructor.Symbol Literal
The# operator creates a compile-time constant symbol. This syntax allows the compiler to track the identifier, ensuring the symbol remains valid even if the identifier is renamed during minification.
_). Attempting to write #_privateIdentifier results in a syntax error.
Symbol Constructor
TheSymbol() constructor creates a symbol at runtime from a string. This is used when the identifier name is dynamic.
Equality and Canonicalization
Symbols are value objects; two symbols are equal if they represent the same identifier. However, the behavior of equality between a symbol literal and a constructed symbol depends on the compilation mode.- Dart VM (JIT): The compiler preserves identifier names.
#myMethodis equivalent toSymbol('myMethod'). - Dart Web / AOT (Minified): The compiler minifies identifiers to reduce code size (e.g.,
myMethodbecomesa).- The literal
#myMethodis compiled into the symbol for the minified name (e.g.,#a). - The constructor
Symbol('myMethod')creates a symbol for the literal string “myMethod”. - Consequently,
#myMethod != Symbol('myMethod').
- The literal
Compilation and Minification Behavior
The distinction betweenString and Symbol is critical during the compilation process.
- Symbol Literals (
#id): These are compiler-aware. If the Dart compiler minifies the functionmyMethodtox, the symbol literal#myMethodcompiles to#x. This ensures that references to the identifier remain consistent within the compiled binary. - Symbol Constructors (
Symbol('id')): These are opaque to the compiler.Symbol('myMethod')will always produce a symbol representing the string “myMethod”, regardless of how the actual code is minified.
Symbol(string_name) to access members dynamically will fail in minified environments, as the runtime member name (e.g., x) no longer matches the constructed symbol name (e.g., myMethod).
Private Identifiers
Dart distinguishes between public and private identifiers. A symbol representing a private identifier encodes both the name and the library in which it is defined. This prevents name collisions between private members of the same name defined in different libraries. While private symbols exist at runtime (for example, passed tonoSuchMethod when a private member is missing), they cannot be created using the # syntax.
Master Dart with Deep Grasping Methodology!Learn More





