Types
Types define the shape of your data. These can either be records, made with the
Reactive.Field command, or tagged unions, made with the Reactive.Variant
command.
Reactive.Module("People", () => {
Reactive.Type("Person", () => { // a record — has Fields
Reactive.Field("name", Text);
Reactive.Field("age", Maths.Real);
});
Reactive.Union("Contact", () => { // a union — has Variants
Reactive.Variant("email", Text);
Reactive.Variant("phone", Text);
});
});Record types
Record types contain a set of fields which are all present in any instance of this type.
Definition
Declare a Reactive.Type and give its body a Reactive.Field for each named part, along
with the type of that part.
Reactive.Type("Person", () => {
Reactive.Field("name", Text);
Reactive.Field("age", Maths.Real);
});Creation
The type is its own constructor. Call it with one positional argument per field, in the order they were declared, to make an instance.
const ada = People.Person("Ada Lovelace", 36);Using
Reach a field with plain dotted access. ada.name is the reactive value for that field, the same
expression you read from.
Content.Text(ada.name); // read the fieldWriting
If a field is part of an object held as state, it can also be updated by any function that can update its input. The field carries its own writable half, so passing it to an input writes straight back into the state.
const ada = Reactive.State(People.Person)(People.Person("Ada Lovelace", 36));
Input.Text(ada.name); // edit the field — writes back into the stateReversibility
Because the field is settable, you can also drive it from a reverse: set the field inside a reverse command and a write to the derived value flows straight back into it.
const naming = Reactive.Reverse((name) => {
Reactive.Set(ada.name, name); // the write flows back into the field
});Tagged union types
Tagged union types hold exactly one of a set of named variants at a time. The tag says which variant is in play, and each variant carries a value of its own type.
Definition
Give the Reactive.Union body a Reactive.Variant for each variant. Variant names are
lowercase.
Reactive.Union("Contact", () => {
Reactive.Variant("email", Text);
Reactive.Variant("phone", Text);
});Creation
Call the variant by name to make a value tagged as that variant, passing the variant's value.
const how = People.Contact.email("ada@engine.org");Using
Reaching a variant yields an optional that is present only when the value is currently that variant, so you match by running a block on the variant you care about; the unwrapped value arrives as an argument.
Collection.Optional.If(how.email, () => {
const address = Reactive.Argument(); // the Text, present only when tagged email
Content.Text(address);
});Built-in types
The scalar leaves ship with the framework and can be used as field, option and argument types anywhere. Each has a page in the module reference:
Text: text stringsMaths.Real: real numbersMaths.Integer: whole numbersLogic.Maybe: true or false