Boolean field
The two-state flag. One `boolean` column, a `z.boolean()` schema, five filter operators, and no arguments to get wrong.
| Surface | Detail |
|---|---|
| Signature | f.boolean() |
| Arguments | none, there is no second form of the call |
| Column | boolean |
| Schema | z.boolean() |
| Filter operators | the boolean set, five entries, below |
| Admin form | a checkbox, or a switch when you ask for one |
| Admin cell | a badge reading Yes or No |
| Type-specific methods | none, the shared chain is the whole surface |
import { collection } from "#questpie/factories";
export const posts = collection("posts").fields(({ f }) => ({
published: f.boolean().default(false).required(),
featured: f.boolean(),
}));published is NOT NULL with a Postgres default of false, and the key is
optional on insert because the default fills it. featured is nullable, so it
reads back as boolean | null and models three states rather than two.
Methods
The type declares no methods of its own. Three from the base chain carry the weight here.
| Method | Effect |
|---|---|
.required() | NOT NULL, and the key is required on insert |
.default(v) | Writes a column default, and makes the key optional on insert |
.localized() | Moves the column into <collection>_i18n, one value per locale |
.label(), .description(), .access(), .hooks() and the rest of the base
chain behave here exactly as on any other type.
`.default()` is checked against `boolean`
The argument is constrained to the field's own data type, so
f.boolean().default("yes") does not compile. It accepts a literal, a
factory, or a raw SQL expression. The value lands on the Postgres column, not
on the insert payload.
Filtering
Boolean carries booleanOps, five operators.
| Operator | Operand | Matches |
|---|---|---|
eq / ne | boolean | Equal, not equal |
not | boolean, or null | Not equal, or IS NOT NULL when given null |
isNull / isNotNull | boolean | Pass false and each inverts |
A bare value is the shorthand for eq, and on a nullable boolean a bare null
compiles to IS NULL. Both short forms live in the generated where type rather
than beside it, and .required() drops null from it.
const { docs } = await app.collections.posts.find({
where: { published: true, featured: { isNull: true } },
});There is nothing else. No in, no gt, because a column with two values has
nothing to order or enumerate.
In the admin
The form control is BooleanField, a checkbox. The list cell is BooleanCell,
a badge reading Yes for a truthy value and No for everything else.
.admin() is the field extension @questpie/admin registers, and one key on it
is boolean-specific.
| Key | Type | Default | Effect |
|---|---|---|---|
displayAs | "checkbox" | "switch" | "checkbox" | Swaps the checkbox for a toggle switch |
emailNotifications: f.boolean().default(true).admin({ displayAs: "switch" }),The rest of the keys on .admin() are the shared ones every field takes.
`null` and `false` are indistinguishable
Both controls render !!value, so an unset boolean shows unchecked and its
cell reads No. The change handler always writes true or false, which means
the admin can never put null back once a person touches the control.
The list filter sheet cannot filter a boolean
It switches on the field registry name, boolean, while its two-state branch
tests for checkbox and switch. Neither matches, so the field falls through
to the presence-only list, is empty and is not empty. Filter through the API
instead.
A localized boolean gets the locale indicator beside its label, the same as any other localized field.
Lists
.array() replaces the column with jsonb holding a list of booleans and swaps
the five operators for the multi-value set.
answers: f.boolean().array().maxItems(20),The admin has no control for a list of booleans
ArrayField picks its item control from an allowlist of five type names, and
boolean is not among them, so each item falls back to a text input. What
that input produces is a string, which z.array(z.boolean()) rejects on save.
Types
A boolean contributes boolean to the row, insert and update shapes, and
nothing needs annotating.
type Post = typeof posts.$infer.select;
// ^? { published: boolean; featured: boolean | null; ... }.required() makes it non-null on read and required on insert. .default()
makes it optional on insert. Without either, the key is optional and the value
is boolean | null.
Related
Select is where a flag belongs once it grows past two states, and it narrows the read type to the literal union of its values.
Arrays covers what .array() does to reads, writes
and filters, and why the item control falls back to text.
Reading and writing has the rest of the query
language, AND, OR, NOT, orderBy and pagination.
Validation covers the derived schema and .zod(),
the way to add a check the type does not carry.