install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/zod-array-validation" ~/.claude/skills/intense-visions-harness-engineering-zod-array-validation-aad595 && rm -rf "$T"
manifest:
agents/skills/codex/zod-array-validation/SKILL.mdsource content
Zod Array Validation
Validate arrays, tuples, records, maps, and sets with Zod's collection primitives
When to Use
- Validating lists of items with consistent shape (e.g., API response arrays, batch inputs)
- Validating key-value maps where keys and values have known types
- Working with fixed-length, typed positional data using tuples
- Ensuring collections meet cardinality constraints (non-empty, length limits)
Instructions
- Use
for lists of items with a uniform element schema:z.array()
import { z } from 'zod'; const TagsSchema = z.array(z.string()); const NumberListSchema = z.array(z.number().positive()); const UserListSchema = z.array(UserSchema);
- Constrain array length with
,.min()
, and.max()
:.length()
const AtLeastOneSchema = z.array(z.string()).min(1, 'At least one item required'); const BoundedSchema = z.array(z.number()).min(1).max(10); const ExactSizeSchema = z.array(z.string()).length(3, 'Must have exactly 3 items');
- Use
as a type-aware alternative to.nonempty()
— the inferred type becomes a non-empty tuple:.min(1)
const NonEmptyTags = z.array(z.string()).nonempty('At least one tag is required'); type NonEmptyTags = z.infer<typeof NonEmptyTags>; // [string, ...string[]]
- Use
for fixed-length arrays with positional types:z.tuple()
const PointSchema = z.tuple([z.number(), z.number()]); // [x, y] — exactly two numbers const RGBSchema = z.tuple([ z.number().min(0).max(255), z.number().min(0).max(255), z.number().min(0).max(255), ]); // Tuple with rest element (fixed prefix + variable suffix) const AtLeastTwoStrings = z.tuple([z.string(), z.string()]).rest(z.string());
- Use
for key-value maps where keys are strings and values share a type:z.record()
// Record with string keys and number values const ScoreMapSchema = z.record(z.number()); // Equivalent to { [key: string]: number } // Record with validated string keys const EnvVarsSchema = z.record(z.string().min(1)); // Record with typed keys (uses z.enum or z.string()) const FeatFlagsSchema = z.record(z.enum(['featureA', 'featureB', 'featureC']), z.boolean());
- Use
for JavaScriptz.map()
objects:Map
const StringToNumberMap = z.map(z.string(), z.number()); // Parses: new Map([['a', 1], ['b', 2]])
- Use
for JavaScriptz.set()
objects:Set
const UniqueTagsSchema = z.set(z.string()); const BoundedSetSchema = z.set(z.number()).min(1).max(5); // Parses: new Set([1, 2, 3])
- Use
to access the element schema of an array for composition:.element
const ItemsSchema = z.array(z.object({ id: z.string(), name: z.string() })); const ItemSchema = ItemsSchema.element; // z.ZodObject<...> type Item = z.infer<typeof ItemSchema>;
Details
Array vs tuple — when to choose:
| Scenario | Use |
|---|---|
| Variable-length, homogeneous items | |
| Fixed-length, positional items | |
| Key-value pairs with string keys | |
| JS Map/Set preservation | / |
Unique element validation:
Zod does not have built-in uniqueness checking. Use
.refine():
const UniqueStringsSchema = z.array(z.string()).refine((arr) => new Set(arr).size === arr.length, { message: 'Array must contain unique values', });
Transforming arrays:
// Sort after parsing const SortedNumbersSchema = z.array(z.number()).transform((arr) => [...arr].sort((a, b) => a - b)); // Deduplicate const DeduplicatedSchema = z.array(z.string()).transform((arr) => [...new Set(arr)]); // Flatten const FlatTagsSchema = z.array(z.array(z.string())).transform((arr) => arr.flat());
Paginated response pattern:
function paginatedSchema<T extends z.ZodTypeAny>(itemSchema: T) { return z.object({ data: z.array(itemSchema), total: z.number().int().nonnegative(), page: z.number().int().positive(), pageSize: z.number().int().positive(), }); } const PaginatedUsersSchema = paginatedSchema(UserSchema); type PaginatedUsers = z.infer<typeof PaginatedUsersSchema>;
Source
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.