shape

How to require fields#

Goal: make a property mandatory, so validation fails when it is missing.

Recipe: use a type marker#

A literal value is optional; a type marker is required.

Language Required markers
TS/JS String, Number, Boolean, Object, Array, Function, Symbol, Date (the globals) and Integer (from shape)
Go shape.String, shape.Number, shape.Boolean, shape.Object, shape.Array, shape.Function, shape.Integer, shape.Date

Any / shape.Any is not a required marker—it accepts an absent value. To require a value of any type use Required(Any) (or bare Required()).

TS

Shape({
  name:  String,   // required string
  age:   Number,   // required number
  admin: Boolean,  // required boolean
})

Go

shape.MustShape(map[string]any{
    "name":  shape.String,
    "age":   shape.Number,
    "admin": shape.Boolean,
})

A missing required field fails with … because the property is missing.

Require a shape that already has a builder#

Wrap it with Required:

Shape({
  email: Required(Check(/^.+@.+$/)),
  tags:  Required([String]),   // required, non-defaulting array
})

The inverse: force optional#

If a value would otherwise be required (for example, under a Check), use Optional, or use Skip to make it optional and skip default injection entirely.

Shape({ note: Optional(String) })({})  // → { note: '' }: absent is allowed, the empty value is injected
Shape({ note: Skip(String) })({})      // → {}: absent → key omitted, not defaulted

Make every property optional at once#

Partial does to each declared property what Optional does to one:

Shape(Partial({ name: String, age: Number }))({})   // → { name: '', age: 0 }

Allow null#

A required field rejects null—it is a present value of the wrong type. Use Nullable to accept it; absent is still governed by required/optional:

Shape({ note: Nullable(String) })({ note: null })   // → { note: null }
Shape({ note: Nullable(String) })({})               // throws: required

Notes#