Skip to main content
In Dart, Runes are an iterable sequence of 32-bit Unicode code points that represent a string. Because Dart strings are inherently sequences of UTF-16 code units, characters outside the Basic Multilingual Plane (BMP)—such as emojis or complex symbols—are represented in memory by surrogate pairs (two 16-bit units). The Runes class abstracts this UTF-16 encoding complexity, allowing developers to interact directly with the underlying 32-bit Unicode code points.

Syntax and String Literals

Within a Dart string literal, Unicode code points are expressed using the \u escape sequence followed by a hexadecimal value.
  • 4-digit hexadecimal: Used for characters within the BMP.
  • Curly braces {}: Required for hexadecimal values containing more or fewer than 4 digits (characters outside the BMP).

Technical Mechanics: codeUnits vs runes

The distinction between a standard Dart String and Runes becomes apparent when inspecting string length and character data. A string’s .length property returns the number of UTF-16 code units, not the number of visible characters. The .runes property returns an Iterable<int> representing the actual Unicode code points.

Instantiation and Conversion

You can instantiate a Runes object directly from a string, and you can reconstruct a String from an iterable of runes using the String.fromCharCodes() constructor.

Character API Alternative

While Runes provide raw integer code points, Dart also offers the characters package (often exposed via the String.characters extension). While Runes handle 32-bit code points, characters handle grapheme clusters (user-perceived characters), which is necessary when a single visual character is composed of multiple Unicode code points (e.g., an emoji with a skin tone modifier).
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More