Shared types
All Motoko types are divided into sets. The smallest is the set of shared types. Shared types are part of the larger set of stable types.
A shared type’s value can be easily exchanged with other actors. To prevent issues associated with sharing mutable state across actors, all shared types are immutable. This immutability allows values to be transmitted safely by copying data, avoiding the complexity and risks of sharing stateful or mutable objects.
Motoko’s shared types also have a natural translation to Candid types.
Operationally, you can think of shared types as the subset of types that can be serialized to Candid.
In Motoko, shared functions are used to transmit values between actors. Unlike other functions, their arguments and results are restricted to shared types. This restriction allows the arguments and results to be translated and transmitted as Candid.
These functions are shared because they are also values of shared types and can be communicated to other actors.
Importance of shared types
Section titled “Importance of shared types”Shareability is essential for several reasons:
- Shared types ensure data can be safely serialized and deserialized across network boundaries.
- Restricting sharing to immutable data prevents synchronization issues between canisters.
- Shared types map directly to Candid, enabling interaction between canisters written in different languages.
- Web and mobile frontends communicate with canisters using shared types.
Common shared types
Section titled “Common shared types”Primitive types
Section titled “Primitive types”Most primitive types are shared by default.
// Numbers, text, and booleans are sharedlet number : Nat = 42;let message : Text = "Hello IC";let flag : Bool = true;Immutable collections
Section titled “Immutable collections”Collections that cannot be modified after creation are shared, including immutable arrays and tuples.
// Immutable arrays are sharedlet names : [Text] = ["Motoko", "Ghost", "Astronaut"];
// Tuples of shared types are sharedlet person : (Text, Nat) = ("Motoko", 25);Records with immutable fields
Section titled “Records with immutable fields”Objects with immutable fields containing shared types are shared, including records.
// Records with immutable fields are sharedlet user = { id = "usr123"; name = "Motoko"; age = 30;};Variants with shared type tags
Section titled “Variants with shared type tags”Variant types are shared when their tags contain shared types.
// Variant types with shared tags are sharedtype Result = { #ok : Nat; #error : Text;};
let success : Result = #ok(200);let failure : Result = #error("Operation failed");Option types
Section titled “Option types”Option types are shared when they contain shared types.
// Option types with shared inner types are sharedlet maybeGreeting : ?Text = ?"Hello";let nothing : ?Nat = null;Actor references
Section titled “Actor references”References to actors are shared, allowing canisters to call each other.
// Actor types are sharedtype CounterActor = actor { increment : shared () -> async Nat; getValue : shared query () -> async Nat;};Shared functions
Section titled “Shared functions”Function types marked as shared are sharable.
// Shared function types are sharedtype Callback = shared (Nat) -> async ();Non-shared types
Section titled “Non-shared types”Certain types cannot be shared between canisters.
Mutable collections
Section titled “Mutable collections”// Mutable arrays are NOT sharedlet mutableArray : [var Nat] = [var 1, 2, 3];Objects with mutable fields
Section titled “Objects with mutable fields”// Objects with mutable fields are NOT sharedlet mutableUser = { var name = "Motoko"; var age = 30;};Error types
Section titled “Error types”// The Error type is NOT sharedlet err : Error = Error.reject("Something went wrong");Objects containing non-shared types
Section titled “Objects containing non-shared types”// Objects containing non-shared types are NOT sharedlet complex = { name = "Document"; contents = [var 1, 2, 3]; // Contains a mutable array};