All free skills / Other majors
superstruct 2.x
Use Superstruct ^2.0.0 for runtime validation, coercion, defaults, refinements, and object-shape utilities. Prefer the current named-export API; do not copy older struct.object/User.assert examples.
- For
superstruct@2.0.2- Verified
- 2026-09-08, 4 examples executed
- Skill package
@modootoday/pmcp-superstruct@2.0.0
Use this skill for free
No PMCP login or subscription is required. Download the original instructions, or install the content-only archive with your project's package manager.
Download SKILL.md · Download package archive
npm install --save-dev https://pmcp.build/skills/superstruct/2/package.tgz
PMCP discovers the installed package's instructions. Connect your runtime after installation.
Archive integrity
sha512-FpCnlGytffLvNaC/asF5VkFhFFiENZV5qU5MS68PCrSJP2pBpt0xZWfCS31SyW8X/d1wVGzfek1yRmwAVkbbpQ==Complete instructions
Verified against superstruct@2.0.2 on 2026-09-08. 4 of 4 examples executed.
Superstruct 2.x
Import and version boundary
Use named exports from superstruct, or a namespace import:
import { object, string, number, assert } from 'superstruct'
const User = object({ name: string(), age: number() })
assert(data, User)
import * as s from 'superstruct' is also supported (s.object(...), s.number(), and so on).
This skill targets ^2.0.0. Node.js 14 is deprecated by the maintainers and is no longer tested.
Core operations
assert(value, struct, message?)throws when validation fails and narrows the value in TypeScript.create(value, struct, message?)validates and returns the coerced/defaulted value.is(value, struct)returns a type guard and does not throw.mask(value, struct, message?)validates and returns a value limited to the struct's recognized shape.validate(value, struct, options)returns[error, value]; use{}when no validation options are needed.StructErroris the exported error class for validation failures.
An object() struct validates its declared object shape. Do not assume that arbitrary extra properties make the input valid. Use type() when the documented shape should permit additional properties.
import { strict as nodeAssert } from 'node:assert'
import { StructError, assert, create, is, mask, number, object, string, validate } from 'superstruct'
const User = object({ id: number(), name: string() })
const input = { id: 1, name: 'Ada' }
nodeAssert.equal(is(input, User), true)
nodeAssert.deepEqual(create(input, User), input)
nodeAssert.deepEqual(mask(input, User), input)
const [error, value] = validate(input, User, {})
nodeAssert.equal(error, undefined)
nodeAssert.deepEqual(value, input)
assert(input, User, 'The user is invalid!')
const [badError] = validate({ id: 'wrong', name: 'Ada' }, User, {})
nodeAssert.ok(badError instanceof StructError)
Struct factories
The documented factories are any, array, bigint, boolean, date, enums, func, instance, integer, intersection, literal, map, never, number, nullable, object, optional, record, regexp, set, string, tuple, type, union, and unknown.
Use factory calls for constraints and nested structures:
const Article = object({
tags: array(string()),
author: object({ id: number() }),
})
object() describes a recognized object shape. type() is the alternative shape that permits additional properties. optional() and nullable() express those states explicitly.
Custom types use define(name, validator), or struct(...) for custom struct construction. The documented email example is:
const Email = define('Email', isEmail)
Refinements
Use empty, max, min, nonempty, pattern, size, and refine to add constraints. Examples include min(integer(), 0), size(string(), 1, 100), and a named predicate with refine.
import { strict as nodeAssert } from 'node:assert'
import { integer, min, nonempty, pattern, refine, size, string, validate } from 'superstruct'
const Index = min(integer(), 0)
const Name = size(nonempty(string()), 1, 20)
const StartsWithThe = refine(string(), 'StartsWithThe', (value) => {
return value.startsWith('The') && value.length > 3
})
const Hex = pattern(string(), /^[0-9a-f]+$/i)
nodeAssert.equal(validate(3, Index, {})[0], undefined)
nodeAssert.equal(validate('', Name, {})[0] instanceof Error, true)
nodeAssert.equal(validate('The book', StartsWithThe, {})[0], undefined)
nodeAssert.equal(validate('abc', Hex, {})[0], undefined)
Coercion and defaults
coerce(target, source, transform)transforms a value before applying the target struct.create()is the current operation for validating and coercing a value; do not use the oldcoerce(data, User)operation shape.defaulted(struct, value)supplies a value when the input is absent.trimmed(string())trims string input.
import { strict as nodeAssert } from 'node:assert'
import { coerce, create, defaulted, number, object, string, trimmed } from 'superstruct'
const MyNumber = coerce(number(), string(), (value) => parseFloat(value))
nodeAssert.equal(create('42', MyNumber), 42)
const User = defaulted(object({ id: number(), name: string() }), { id: 1, name: 'Anonymous' })
nodeAssert.deepEqual(create({}, User), { id: 1, name: 'Anonymous' })
nodeAssert.equal(create(' Ada ', trimmed(string())), 'Ada')
Struct utilities
The documented utility exports are assign, deprecated, dynamic, lazy, omit, partial, and pick. They compose or derive structs. Recursive structures use lazy, for example:
const Node = object({ id: number(), children: lazy(() => array(Node)) })
omit, pick, and partial derive object structs:
const PublicUser = omit(object({ id: number(), name: string() }), ['name'])
const OptionalUser = partial(object({ id: number(), name: string() }))
import { strict as nodeAssert } from 'node:assert'
import { array, lazy, number, object, omit, partial, pick, string, validate } from 'superstruct'
const Node = object({ id: number(), children: lazy(() => array(Node)) })
nodeAssert.equal(validate({ id: 1, children: [{ id: 2, children: [] }] }, Node, {})[0], undefined)
const User = object({ id: number(), name: string(), role: string() })
const PublicUser = omit(User, ['name'])
const NamedUser = pick(User, ['id', 'name'])
const OptionalUser = partial(object({ id: number(), name: string() }))
nodeAssert.equal(validate({ id: 1, role: 'admin' }, PublicUser, {})[0], undefined)
nodeAssert.equal(validate({ id: 1, name: 'Ada' }, NamedUser, {})[0], undefined)
nodeAssert.equal(validate({}, OptionalUser, {})[0], undefined)
v2 migration traps
Do not use examples from the older pre-1.0 API merely because they remain common in existing code:
struct.object({ name: 'string' })→object({ name: string() })User.assert(data)→assert(data, User)struct('email', isEmail)→define('email', isEmail)refinement(...)→refine(...)coercion(...)→coerce(...)coerce(data, User)→create(data, User)length(string(), 1, 100)→size(string(), 1, 100)StructType<typeof User>→Infer<typeof User>- old
interface,enum, andfunctionnames →type,enums, andfunc - defaults and optional values → explicit
defaulted(...)andoptional(...)
In v2, arrays correctly fail validation against object(), type(), and record(). Object coercion no longer turns arrays into objects with numeric index keys. mask() also handles union members correctly. Do not preserve workarounds written for those older behaviors.
What this skill does not cover
It does not cover every individual factory's full option and error-message behavior, TypeScript Infer usage beyond the migration note, browser UMD loading, or application-specific validation schemas. It also does not cover a CLI, test runner, framework integration, network behavior, or filesystem behavior; Superstruct's documented usage is direct library code.