Status: implemented
A primitive used as a schema admits exactly itself: null, undefined, true, 42, 'hello' and 7n are each a schema whose one value is that primitive. The comparison is Object.is, so the constant NaN admits NaN, and 0 and -0 are two schemas with one value each.
import { parse } from 'functionalscript/fjs/rtti/parse/module.f.mjs'
parse('circle')('circle') // ['ok', 'circle']
parse('circle')('square') // ['error', …]
parse({ kind: 'circle', r: 1 })({ kind: 'circle', r: 1 }) // ['ok', …]
A constant is the usual tag of a tagged union: or({ kind: 'circle', r: number }, { kind: 'square', side: number }) reads the kind to tell its members apart (unions). A struct or a tuple used as a schema is a constant too, read member by member (structs and tuples are closed).
undefined is a constant like the others: { a: undefined } needs the key a, holding undefined. It is not absence, which is option's.
Inside a recursive definition a constant is written as a thunk, () => ['const', c], so that every schema the definition names is a function (recursion).
The demo on this page runs two lessons. Zero and minus zero is a pair: the value -0 is refused by the schema 0 and accepted by the schema -0; type export default 0; to see the answers swap. Tagged union is or({ kind: 'circle', r: number }, { kind: 'square', side: number }) against {"kind":"circle","r":1}; change the kind to "triangle", or give the circle a side, to see both readers refuse it. The lessons are defined in sample.f.mjs, and the module page's demo lists them among all the others.
- TypeScript: literal types
- JSON Schema:
const(reference). A bigint constant becomes a number, which is lossy pastNumber.MAX_SAFE_INTEGER, andundefinedbecomes{ "not": {} }, since no JSON value isundefined.