Status: implemented
option admits absence: the member that is not there. It is a nullary schema like boolean, and a member that may be omitted says so by union.
{ a: or(option, number) } // `a` may be absent, or a number
{ a: or(number, undefined) } // `a` must be present, may hold `undefined`
{ a: or(option, number, undefined) } // absent, a number, or a present `undefined`
[3, or(option, number)] // position 1 may be absent: `[3]`
Absence is not a spelling of the value undefined: {} and { a: undefined } are two distinct values, and only a set admitting absence accepts the first. A member is required exactly when its set excludes absence, so a struct key or a tuple position without option must be there (structs and tuples are closed).
Absence is observable only at a container position. No caller can hand a reader an argument that is not there, so a top-level schema admitting absence accepts exactly what the rest of its union accepts. A tuple position is absent only past the end of the array, since FunctionalScript builds no array with a hole and the readers read none (what the readers assume of a value). A container's rest never sees an absent member either.
Neither reader fills an absent member in: parse({ a: or(option, number) })({}) builds {}, with no key a, and validate hands back the {} it was given.
The demo on this page runs the Absent vs undefined lesson: {} is accepted by { a: or(option, number) } and refused by { a: or(number, undefined) }. Type export default {"a":undefined}; to see the answers swap. The lesson is defined in sample.f.mjs, and the module page's demo lists it among all the others.
- TypeScript: optional properties.
Ts<>rendersor(option, t)as an optional key,a?: Ts<t>; the difference fromundefinedis the oneexactOptionalPropertyTypesdraws. - JSON Schema: a key admitting absence is left out of
required, and a tuple position out ofminItems(object)
option in module.f.mjs; the absent bit of a member's unit set in data.