Skip to main content
An external constructor in Dart is a constructor declaration that lacks an implementation body within the Dart source code. By using the external keyword, the constructor delegates its instantiation logic, memory allocation, and initialization to an external host environment, such as the Dart Virtual Machine (VM), a JavaScript engine, or native code via the Foreign Function Interface (FFI).

Syntax

An external constructor is declared using the external modifier before the constructor name. It must be terminated with a semicolon rather than a block body.
class NativeBuffer {
  // Non-nullable fields must be initialized at declaration or marked external 
  // when using an external generative constructor.
  final int defaultCapacity = 256;
  external int size;

  // External generative constructor (initializing formals are prohibited)
  external NativeBuffer(int size);

  // External named constructor
  external NativeBuffer.allocate(int size);
  
  // External factory constructor
  external factory NativeBuffer.create();
}

Technical Characteristics

  • Absence of Implementation: An external constructor cannot have a block body ({}), an expression body (=>), or an initializer list (: field = value). The declaration acts strictly as a signature contract.
  • Parameter Restrictions: The Dart language specification explicitly prohibits the use of initializing formals (this.field) and super-initializing formals (super.field) in external constructors. These constructs represent Dart-level initialization logic, which is strictly the responsibility of the external implementation.
  • Field Initialization Constraints: Because external generative constructors cannot initialize fields (lacking both initializing formals and initializer lists), a class containing uninitialized final or non-nullable instance variables cannot use an external generative constructor. To satisfy Dart’s sound null safety and definite assignment rules, you must use one of the following approaches:
    1. Use an external factory constructor instead of a generative constructor.
    2. Initialize the fields directly at their declaration point.
    3. Mark the fields themselves as external (a common pattern in JS interop and FFI).
  • Compiler Resolution: The Dart compiler expects the implementation to be provided by the underlying runtime. If the runtime fails to link the external declaration to a native implementation, invoking the constructor results in a runtime NoSuchMethodError.
  • SDK Patching: Within the Dart SDK, external constructors are frequently paired with the @patch annotation. The external keyword declares the API in the public-facing Dart interface, while a separate, platform-specific file provides the @patch implementation that interfaces directly with C++ or JavaScript.
  • Factory vs. Generative: The external keyword can be applied to both generative constructors and factory constructors. When applied to a factory, the external environment is responsible for returning an instance that conforms to the class type, rather than just allocating memory for a new instance.
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More