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▾
Performance▾
Native▾
Development▾

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 to string and 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 Int field; any decimal makes it Float.
  • No TypeScript enum. Akan never uses the enum keyword; a choice field is always an enumOf class.
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 draft reads as l("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.ToggleSelect and Field.MultiToggleSelect take 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:
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
  • Select shows raw values. options={cnst.PostStatus} works, but the list reads draft, 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
  • set adds or replaces. A new id goes to the end; a known id is swapped in place.
  • pick or get. pick(id) throws for a missing id; get(id) returns undefined.
  • filter makes a smaller DataList. The original list stays as it was.
Methods At A Glance
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:
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, then save. set changes 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 postList current; write an action only for a custom endpoint such as addAdminRole.

Which One To Use

A label-like value is an Enum; a collection of records with ids is a DataList.
QuestionEnumDataList
What it holdsOne value from a fixed setRecords that each have an id
ExamplesStatus, role, type, size, visibilityUsers, files, posts, selected rows
Where it lives*.constant.ts, as a field typeStore state, or new DataList(items)
Typical callPostStatus.has(value)postList.pick(id)
  • DataList is not a database query. It only works on data already loaded into the app, so filter sees 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.draft and 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) or new DataList(list).sort(compare), never sort on a store list directly.
  • Remember the shortcut. Value choices are Enum; id collections are DataList.

Released under the MIT License

Connect your AI to these docs

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js All rights reserved.System managed bybassman