Types And Values
- Every value has a concrete type; Nenu does not rely on truthiness or implicit cross-type conversion.
- Primitive, named, optional, collection, and structural types follow different compatibility rules.
- Inference removes repeated type spelling, but it never weakens the type contract.
The Type Families
| Family | Examples | Identity rule |
|---|---|---|
| Primitive | string, number, bool, time | Compatible by primitive kind. |
| Media | image, file | Fixed metadata objects supplied by the platform. |
| Named value type | ExpenseDraft | Structurally compatible with an equal shape. |
| Entity | Room, Expense | Nominal: the declared entity name matters. |
| Enum | ExpenseStatus | Nominal: variants belong to one enum. |
| Optional scalar | string?, Expense? | Either the wrapped value or absent. |
| Collection | Expense[], number{} | Element type and container shape must match. |
| Structural shape | { label: string, amount: number } | Field names, types, and optional markers must match; order does not matter. |
Literal Values
1string title = "Internet"2number amount = 72.503bool shared = true4time recorded_at = time.now()5string? note = ?67number[] shares = [24.17, 24.17, 24.16]8number{} balances = { alice: 24.17, sam: -24.17 }Strings use double quotes. Numbers cover integer and decimal values. Booleans are exactly true or false. The lone ? value means absent and only fits an optional scalar. Array and map literals infer from their members when non-empty.
Inference Keeps A Real Type
1number total = 72.502string label = "Internet"Both tabs produce a number named total and a string named label. Inference only discovers the type from the first value. A later incompatible assignment is still rejected.
1total = 72.502total = 8034// Invalid: total remains number5total = "eighty"Construction And Compatibility
1type BalanceRow {2 label: string3 amount: number4}56BalanceRow row = {7 amount: 24.178 label: "Sam owes Alex"9}1011{ label: string, amount: number } same_shape = rowThe named value type and the inline shape are compatible because they have the same fields and types. Field order does not matter. A stored entity with those fields remains a different nominal type because entity identity carries storage meaning.
No Truthiness Or Silent Conversion
| Intent | Wrong | Correct |
|---|---|---|
| Check a number | if amount { ... } | if amount > 0 { ... } |
| Check a string | if title { ... } | if title != "" { ... } |
| Check an optional | if note { ... } | with note as text { ... } |
| Convert a value | Assume assignment converts it | Use a documented method or keep matching types. |
Common Mistakes
| Mistake | Use instead |
|---|---|
| Treat a number or string as a boolean | Write an explicit comparison. |
| Assume assignment converts between types | Keep compatible types or use a documented method. |
| Treat entities as structural shapes | Remember that entity identity is nominal. |
| Infer an empty collection or absent value | Write the explicit expected type. |
