How to rename properties and reuse shapes#
Goal: rename a property after validation, or define a shape once and reference it elsewhere (including recursively).
Rename a property#
Rename({ name }) validates the value and moves it to a new key.
TS
const { Shape, Rename } = require('shape') // Number is the JS global
const shape = Shape({ id: Rename({ name: 'userId' }, Number) })
shape({ id: 7 }) // → { userId: 7 }
Go
s := shape.MustShape(map[string]any{
"id": shape.Rename("userId", shape.Number),
})
Options (passed in the first argument object in TS; via RenameWith in Go):
| Option | Effect |
|---|---|
keep |
keep the original key as well as the renamed one |
claim |
list of alternate source keys to pull the value from if absent |
Shape({ userId: Rename({ name: 'userId', claim: ['id', 'uid'] }, Number) })
// accepts { id: 7 } or { uid: 7 } → { userId: 7 }
Define and refer to a shape#
Define(name, shape) records a shape under a name during validation;
Refer(name) substitutes it. This is the basis for recursive shapes.
TS
const { Shape, Define, Refer } = require('shape')
const tree = Shape(Define('node', {
value: Number,
children: [Refer('node')], // each child is another node
}))
tree({ value: 1, children: [{ value: 2, children: [] }] }) // OK
Go
s := shape.MustShape(shape.Define("node", map[string]any{
"value": shape.Number,
"children": []any{shape.Refer("node")},
}))
Fill from a reference even when absent#
By default Refer only substitutes when a value is present (this prevents
infinite loops for self-referential shapes). To substitute even when the value
is missing, enable fill:
TS
Shape({ copy: Refer({ name: 'shared', fill: true }) })
Go
shape.ReferWith("shared", shape.ReferOptions{Fill: true})
A Refer whose name no Define supplies does nothing: the value is
validated by the Refer's own shape, if it has one. To make that a
mistake rather than a no-op, ask for strict:
Shape({ copy: Refer({ name: 'shared', strict: true }) })
// Value "1" for property "copy" refers to "shared", which is not defined.
shape.ReferWith("shared", shape.ReferOptions{Strict: true})
Use
fillonly when the reference is not self-recursive, or you will create an infinite expansion.