Skip to content
Konjure / spatial intelligence

Types and traits

Give values nominal structure and describe shared behavior.

A type owns typed fields and methods. A trait describes methods a value must provide. Neither schedules work: attach a type value to an entity and use a system when it needs to run over time.

Make a type value

The fixture prints 4 and then Some(9): it constructs a nominal type value, then reads a list through an explicit optional value.

Tick 0 · 0.00 sThis device
main.kj⌘ / Ctrl + Enter
Loading the language runtime…
Output 0
No output.

type Name { field: T; func method() -> T { ... } } declares a nominal record. Fields may have defaults. A constructor may omit a defaulted field, but must supply every field without a default; unknown fields and incompatible values are compile errors. Two types with the same fields still have different types. Fields are public.

Methods use the implicit self receiver; do not list it as a parameter. A method that changes self needs a receiver rooted in a mutable binding. The compiler checks every type and method body, including unused ones.

State a behavior contract

trait Readable { func read() -> f32; } states a callable contract. impl Readable for Gauge must provide every required method with exactly that signature. A trait-typed value exposes the trait methods, not arbitrary fields of its implementing type. Type inheritance, associated types, generic bounds, and derivation are not implemented.

Store and pass functions

Write a function type as func(f32) -> f32. A function value can be assigned to a binding, passed to another function, returned, or stored in a typed list or type field. Calls check the same signature in every position.

Tick 0 · 0.00 sThis device
main.kj⌘ / Ctrl + Enter
Loading the language runtime…
Output 0
No output.

Reading a nonmutating method as a value captures a copy of its receiver. Capturing a method that mutates an ordinary type is rejected: use bind[T](entity).method for a callback that updates an entity’s live component.

Specialize ECS helpers

Choose the component type before storing an ECS helper: get[Counter] is a function value; get[Counter](entity) calls it immediately. The same rule applies to has, query, and bind.

ValueFunction type
get[Counter]func(Entity) -> Counter
has[Counter]func(Entity) -> Bool
query[Counter]func() -> List[Entity]
bind[Counter]func(Entity) -> ComponentReference[Counter]
Tick 0 · 0.00 sThis device
main.kj⌘ / Ctrl + Enter
Loading the language runtime…
Output 0
No output.

ComponentReference[Counter] stores an entity/component identity; calling its bound methods resolves the current component. Function parameters, return values, and fields use explicit types; local bindings infer a fixed type from their initializer. Imported type identity is nominal: models.Point is distinct from a local Point.