YouBothAgent▾
You — Business rules and flows you own. Read these yourself.
Both — Know the idea; your agent follows the details.
Agent — Conventions and references your agent follows. Look up as needed.
General▾
Interface▾
Observability▾
DataList & Enum
Enum and DataList are two small helpers you will meet all over Akan code. Enum is for a fixed set of values; DataList is for a list of items that each have an id.
Enum
A fixed set of values
Status, role, type, category: a value that is always one of a few known choices.
enumOf("postStatus", [...] as const)DataList
A list keyed by id
Users, files, posts, selected rows: records you find and replace by id.
userList.pick("u1")Both are imported from
akanjs/base.Enum
Use an Enum when a value must be one of a few known choices. Declared once, it keeps forms, APIs and labels in agreement.
1. Declare It In The Constant File
Declare the class above the model classes, then use it as a field type:
apps/myapp/lib/post/post.constant.ts
- Always add
as const. Without it,PostStatus["value"]widens tostringand a typo compiles. - The first argument is the refName. It is the class name in camelCase:
PostStatus→postStatus. - Numbers work too. Whole numbers make an
Intfield; any decimal makes itFloat. - No TypeScript enum. Akan never uses the
enumkeyword; a choice field is always anenumOfclass.
2. Give Each Value A Label
Translate every value in the dictionary's
.enum() stage, keyed by the refName:apps/myapp/lib/post/post.dictionary.ts
- Every value needs an entry. The stage is typed from
PostStatus, so a missing value is a type error. - Each label gets a key. The value
draftreads asl("postStatus.draft").
3. Use It On Screen
In a form, hand the class straight to a toggle field:
apps/myapp/lib/post/Post.Template.tsx
- Labels come from the dictionary.
Field.ToggleSelectandField.MultiToggleSelecttake the enum class and label each choice by its key. - Pass the setter as is.
onChange={st.do.setStatusOnPost}without an arrow wrapper keeps the field visible to the in-page agent.
To show a saved value, look up the same key. A module-scope map gives each value its own style:
apps/myapp/lib/post/Post.Unit.tsx
- The map covers every value. Typed as
{ [key in cnst.PostStatus["value"]]: string }, it stops compiling when a new value has no class.
4. Work With Values In Code
The class itself carries the values and a few array helpers:
MemberDescription
PostStatus["value"]
The value type,
"draft" | "published" | "archived", for props and parameters.values
Every value, in the order you declared them.
has(value)
Whether a value belongs to the enum, checked at runtime.
indexOf(value)
The value's position in
values, throwing for a value outside the enum.mapfilterforEach
The usual array methods, run over
values.findfindIndex
Like the array methods, but they throw when nothing matches.
refName
The name you passed to
enumOf, here postStatus.A control that takes label/value pairs, such as
Select, needs the labels mapped in:apps/myapp/lib/post/Post.Zone.tsx
Selectshows raw values.options={cnst.PostStatus}works, but the list readsdraft, not the translated label.
DataList
Use a DataList when a list is already loaded and you want to work with it by id. It suits UI state because adding, replacing, picking and filtering are one call each.
The Basics
A DataList keeps exactly one item per id:
apps/myapp/lib/user/user.test.ts
setadds or replaces. A new id goes to the end; a known id is swapped in place.pickorget.pick(id)throws for a missing id;get(id)returnsundefined.filtermakes a smaller DataList. The original list stays as it was.
Methods At A Glance
MethodDescription
new DataList(items)
Builds a list from an array or another DataList, keeping the last item for a repeated id.
set(item)delete(id)
Add or replace, or remove, by id, changing this list in place and returning it.
get(id)pick(id)has(id)
Look up by id:
get may return undefined, pick throws, has answers true or false.indexOf(id)at(idx)pickAt(idx)
Position lookups, where
indexOf and pickAt throw when nothing is there.filterslicesort
Return a new DataList, but
sort also reorders the source array, so sort a copy.mapfindsomeeveryreduceforEachflatMap
The array methods over the items, where
map returns a plain array.lengthvalues
The item count and the underlying array, and the list itself works in
for…of too.save()
Returns a new DataList with the same items, which is what a store needs.
DataList In The Store
Every slice gives the store three DataList keys, and
Load.Units hands you one more. For a post model:NameDescription
postList
The rows the slice has loaded, suffixed for a named slice as in
postListInPublic.postInitList
The rows as the last
init loaded them.postSelection
The rows a user selected, filled by
st.do.selectPost(post).renderList
Load.Units passes the list to this callback as a DataList.Change A Store List
A custom store action writes the changed list back with
save(), as the shared lib's admin store does:libs/shared/lib/admin/admin.store.ts
set, thensave.setchanges the list in place;save()wraps it in a new DataList so the store sees a new value.- Generated actions already do this. Create, update and remove keep
postListcurrent; write an action only for a custom endpoint such asaddAdminRole.


Always hand the store a new DataList.
adminList.set(admin) returns the same instance, and the store compares values by reference, so nothing on screen updates. Finish with .save().Which One To Use
A label-like value is an Enum; a collection of records with ids is a DataList.
| Question | Enum | DataList |
|---|---|---|
| What it holds | One value from a fixed set | Records that each have an id |
| Examples | Status, role, type, size, visibility | Users, files, posts, selected rows |
| Where it lives | *.constant.ts, as a field type | Store state, or new DataList(items) |
| Typical call | PostStatus.has(value) | postList.pick(id) |
- DataList is not a database query. It only works on data already loaded into the app, so
filtersees the loaded rows, not the whole table. - Narrow on the server instead. To fetch fewer rows, add a query filter or a slice.
Tips
- Keep the refName stable. Dictionaries, label keys like
postStatus.draftand API schemas find the enum by it, so renaming it leaves them behind. - Keep DataList items small. Store lists hold light models, which carry only the fields a list needs.
- Sort a copy. Write
list.filter(fn).sort(compare)ornew DataList(list).sort(compare), neversorton a store list directly. - Remember the shortcut. Value choices are Enum; id collections are DataList.