Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Values and types

Values and types

Building a type from other types

Most object types in a real application are slices of an entity or of another object: a create input, a patch input where every field is optional, a public view, a list summary, a v2 response that…

Most object types in a real application are slices of an entity or of another object: a create input, a patch input where every field is optional, a public view, a list summary, a v2 response that adds a field. Instead of writing each field out (title: Todo.title), a type's body can copy fields from other types. The body keeps its ordinary Output { } form. Four kinds of line build it. They are read from top to bottom, and each changes the result of the lines above it:

Line Does
include: [Todo] adds every field of each listed type (types only; never on an Input)
pick: [Todo.id, Todo.title] adds just the listed fields, each keeping its own name
omit: [Todo.internal_note] removes fields present at that point
bar: User.bar a written field: replaces a field of the same name above, or adds a new one
example
type TodoView = Output {    pick: [Todo.id, Todo.title, Todo.status, Todo.due_at]}type TodoDetail = Output {    include: [Todo]    omit: [Todo.deleted_at]    owner_email: User.email}type PatchTodo = Input {    pick: [Todo.title, Todo.due_at]    optional: all}type OrderView = Output {    include: [Order]    lines: List<OrderLineView>  // replaces Order.lines with a view of each line}type TodoReminder = Object {    pick: [Todo.id, Todo.title, Todo.due_at]    owner_email: User.email    days_overdue: DayCount}

Rules:

  • Top to bottom. The same kind of line may appear more than once, and the formatter keeps the order written, because order matters here.
  • Fields keep their declared order. Copied fields stand where their include or pick line is, an include's in the order its type declares them and a pick's in the order listed; a written field that replaces a copied one takes its place. Values, hover and the manifest (each field's order) follow it.
  • Lists are always in brackets, even with one entry: include: [Todo].
  • omit removes only what is there. Omitting a field that is not present at that point is an error, which catches typos and fields since removed.
  • Written fields win. A field you write replaces any field of the same name above it, visibly; otherwise it is added.
  • Copied fields never silently replace copied fields. An include or pick that would replace a field brought in by an earlier include or pick is an error: resolve it with omit or by writing the field. Copied fields are not visible in the declaration, so a clash there would change a type unseen when a source type gains a field.
  • No include on an Input. Taking every field of User would accept any field added to User later, so a client could set a field it was never meant to (the mass-assignment bug). Inputs pick or write their fields. Generated fields such as id and created_at can never appear in an Input.
  • optional makes the listed fields, or all, optional, only on an Input.
  • Copied fields follow their source. Renaming Todo.title renames it in every type that copies it, and its validation rules come with it.
  • No type includes itself. An include that leads back to its own type, directly or through another, is type.copy_cycle.
  • Every built type has a name; there are no inline types in signatures. Hover in your editor shows the final fields and where each came from (title ← Todo.title, lines ← written, replaces Order.lines).
  • Outputs may include. A field added to Todo later reaches TodoDetail, and the committed API record shows the addition in review (HTTP). Fields that policy hides from clients stay hidden when the app runs (Field restrictions).
  • include, pick, omit and optional are reserved and cannot be field names.

Markdown for agents: /docs/building-a-type-from-other-types.md.Built from Jadpo main at a707efb.