Form
Version Note
This documentation describes Swim JS packages v4.0.0 or later. Users of earlier package versions may experience differences in behavior.
A Form defines a conversion between a structural type, and some nominal JavaScript type. The mold
method converts a nominal JavaScript type to an Item. And the cast
method converts an Item to a nominal JavaScript type, if possible.
Here is an example of a custom Form which defines how the conversion of an entity representing how a stock might look. Custom Forms should extend Form
, which can be imported from @swim/structure
. This library should automatically be present in your bundle as a dependency of @swim/client
.
import { Form, Item } from "@swim/structure";
type Stock = {
symbol: string;
price: number;
volume: number;
dailyChange: number;
};
export class StockForm extends Form<Stock | undefined> {
constructor() {
super();
}
// Item to JS object
override cast(item: Item): Stock | undefined {
if (
item.tag === "update" && // make sure message is an update
item.get("update").get("key").stringValue("") && // find key
item.get("price").isDefinite() && // ensure all fields are present
item.get("volume").isDefinite() &&
item.get("movement").isDefinite()
) {
return {
symbol: item.get("update").get("key").stringValue(""),
price: item.get("price").numberValue(0),
volume: item.get("volume").numberValue(0),
dailyChange: item.get("dailyChange").numberValue(0),
};
}
// return undefined for all messages which don't fit the expected format
return undefined;
}
// JS object to Item
override mold(object: Stock, item?: Item): Item {
let result = Item.fromLike(object);
if (item !== void 0) {
result = item.concat(object);
}
return result;
}
}
A downlink which expects to receive data matching the format of a Stock may now use this Form to coerce the Values it receives into a strongly typed Stock
objects. If the Form receives data in an unrecognized format, it will return undefined, which is also part of its type. Remember that isDistinct
is used to check that a Value
is not Extant
or Absent
, and isDefinite
checks that it’s not false
or an empty Record
either.
The example above demonstrates a straightforward use case of converting expected structural types into typed JavaScript objects more comfortable to work with. The possibilites afforded by custom Forms, however, go beyond simple conversion. Further transformation of the data could be performed within Forms as well. While it would likely be cleaner and more efficient to do such operations from inside of a Web Agent (as that is one of their defining purposes), it is wholly possible to do data transformation within a Form as well if one were so inclined.