Socket
Socket
Sign inDemoInstall

zod

Package Overview
Dependencies
Maintainers
1
Versions
361
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zod - npm Package Compare versions

Comparing version 1.1.2 to 1.2.0

lib/src/helpers/maskUtil.d.ts

8

lib/src/helpers/util.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// import { ZodRawShape } from '../types/base';
// import { ZodIntersection } from '../types/intersection';
// import { ZodObject } from '../types/object';
// export type Merge<U extends object, V extends object> = {
// [k in Exclude<keyof U, keyof V>]: U[k];
// } &
// V;
//# sourceMappingURL=util.js.map

2

lib/src/index.d.ts

@@ -41,2 +41,2 @@ import { ZodString, ZodStringDef } from './types/string';

export { ZodString, ZodNumber, ZodBoolean, ZodUndefined, ZodNull, ZodArray, ZodObject, ZodUnion, ZodIntersection, ZodTuple, ZodRecord, ZodFunction, ZodLazy, ZodLiteral, ZodEnum, ZodType, ZodAny, ZodDef, ZodError, };
export { TypeOf, TypeOf as Infer };
export { TypeOf, TypeOf as infer };
import * as z from './types/base';
export declare type ParseParams = {
seen: any[];
};
export declare const ZodParser: (schemaDef: z.ZodTypeDef) => (obj: any, params?: ParseParams) => any;
export declare const applyMask: (schema: z.ZodType<any, z.ZodTypeDef>, mask: any, mode: "omit" | "pick") => any;

@@ -11,186 +11,61 @@ "use strict";

var z = __importStar(require("./types/base"));
var ZodError_1 = require("./ZodError");
// const seen: any[] = [];
// export const ZodParser = (schemaDef: z.ZodTypeDef) => (obj: any) => ZodParserFactory(schemaDef)(obj, { seen: [] });
exports.ZodParser = function (schemaDef) { return function (obj, params) {
if (params === void 0) { params = { seen: [] }; }
var def = schemaDef;
// const { seen } = params;
// console.log(`visit ${schemaDef.t}: ${typeof obj} - ${obj.name || ''}`);
// if (!['number', 'string', 'boolean', 'undefined'].includes(typeof obj)) {
if (params.seen.indexOf(schemaDef) !== -1) {
console.log("seen " + typeof obj + " before: " + obj.name);
return obj;
var array_1 = require("./types/array");
var object_1 = require("./types/object");
exports.applyMask = function (schema, mask, mode) {
var _def = schema._def;
var def = _def;
if (mask === true) {
return schema;
}
else {
params.seen.push(schemaDef);
}
// }
switch (def.t) {
case z.ZodTypes.string:
if (typeof obj !== 'string')
throw ZodError_1.ZodError.fromString("Non-string type: " + typeof obj);
return obj;
case z.ZodTypes.number:
if (typeof obj !== 'number')
throw ZodError_1.ZodError.fromString("Non-number type: " + typeof obj);
if (Number.isNaN(obj)) {
throw ZodError_1.ZodError.fromString("Non-number type: NaN");
else if (typeof mask === 'object' && !Array.isArray(mask)) {
if (def.t === z.ZodTypes.array) {
if (def.type._def.t === z.ZodTypes.object) {
return new array_1.ZodArray({
t: z.ZodTypes.array,
nonempty: def.nonempty,
type: exports.applyMask(def.type, mask, mode),
});
}
return obj;
case z.ZodTypes.boolean:
if (typeof obj !== 'boolean')
throw ZodError_1.ZodError.fromString("Non-boolean type: " + typeof obj);
return obj;
case z.ZodTypes.undefined:
if (obj !== undefined)
throw ZodError_1.ZodError.fromString("Non-undefined type:Found: " + typeof obj);
return obj;
case z.ZodTypes.null:
if (obj !== null)
throw ZodError_1.ZodError.fromString("Non-null type: " + typeof obj);
return obj;
case z.ZodTypes.array:
if (!Array.isArray(obj))
throw ZodError_1.ZodError.fromString("Non-array type: " + typeof obj);
var arrayError_1 = ZodError_1.ZodError.create([]);
if (def.nonempty === true && obj.length === 0) {
throw ZodError_1.ZodError.fromString('Array cannot be empty');
else {
throw new Error("You can only " + mode + " arrays of objects.");
}
var parsedArray = obj.map(function (item, i) {
try {
var parsedItem = def.type.parse(item, params);
return parsedItem;
}
catch (err) {
if (err instanceof ZodError_1.ZodError) {
arrayError_1.mergeChild(i, err);
// arrayErrors.push(`[${i}]: ${err.message}`);
return null;
}
else {
arrayError_1.mergeChild(i, ZodError_1.ZodError.fromString(err.message));
// arrayErrors.push(`[${i}]: ${err.message}`);
return null;
}
}
});
if (!arrayError_1.empty) {
// throw ZodError.fromString(arrayErrors.join('\n\n'));
throw arrayError_1;
}
return parsedArray;
case z.ZodTypes.object:
if (typeof obj !== 'object')
throw ZodError_1.ZodError.fromString("Non-object type: " + typeof obj);
if (Array.isArray(obj))
throw ZodError_1.ZodError.fromString("Non-object type: array");
}
else if (def.t === z.ZodTypes.object) {
var modShape = {};
var shape = def.shape;
if (def.strict) {
var shapeKeys_1 = Object.keys(def.shape);
var objKeys = Object.keys(obj);
var extraKeys = objKeys.filter(function (k) { return shapeKeys_1.indexOf(k) === -1; });
if (extraKeys.length) {
throw ZodError_1.ZodError.fromString("Unexpected key(s) in object: " + extraKeys.map(function (k) { return "'" + k + "'"; }).join(', '));
if (mode === 'pick') {
if (mask === true)
return shape;
for (var key in mask) {
if (!Object.keys(shape).includes(key))
throw new Error("Unknown key in pick: " + key);
modShape[key] = exports.applyMask(shape[key], mask[key], mode);
}
}
var objectError = ZodError_1.ZodError.create([]);
for (var key in shape) {
try {
def.shape[key].parse(obj[key], params);
if (mode === 'omit') {
for (var maskKey in mask) {
if (!Object.keys(shape).includes(maskKey))
throw new Error("Unknown key in omit: " + maskKey);
}
catch (err) {
if (err instanceof ZodError_1.ZodError) {
objectError.mergeChild(key, err);
for (var key in shape) {
if (mask[key] === true) {
continue;
}
else {
objectError.mergeChild(key, ZodError_1.ZodError.fromString(err.message));
else if (typeof mask[key] === 'object') {
modShape[key] = exports.applyMask(shape[key], mask[key], mode);
}
}
}
if (!objectError.empty) {
throw objectError; //ZodError.fromString(objectErrors.join('\n'));
}
return obj;
case z.ZodTypes.union:
for (var _i = 0, _a = def.options; _i < _a.length; _i++) {
var option = _a[_i];
try {
option.parse(obj, params);
return obj;
}
catch (err) { }
}
throw ZodError_1.ZodError.fromString("Type mismatch in union.\nReceived: " + JSON.stringify(obj, null, 2) + "\n\nExpected: " + def.options
.map(function (x) { return x._def.t; })
.join(' OR '));
case z.ZodTypes.intersection:
var errors = [];
try {
def.left.parse(obj, params);
}
catch (err) {
errors.push("Left side of intersection: " + err.message);
}
try {
def.right.parse(obj, params);
}
catch (err) {
errors.push("Right side of intersection: " + err.message);
}
if (!errors.length) {
return obj;
}
throw ZodError_1.ZodError.fromString(errors.join('\n'));
case z.ZodTypes.tuple:
if (!Array.isArray(obj)) {
throw ZodError_1.ZodError.fromString('Non-array type detected; invalid tuple.');
}
if (def.items.length !== obj.length) {
throw ZodError_1.ZodError.fromString("Incorrect number of elements in tuple: expected " + def.items.length + ", got " + obj.length);
}
var parsedTuple = [];
for (var index in obj) {
var item = obj[index];
var itemParser = def.items[index];
try {
parsedTuple.push(itemParser.parse(item, params));
}
catch (err) {
if (err instanceof ZodError_1.ZodError) {
throw err.bubbleUp(index);
}
else {
throw ZodError_1.ZodError.fromString(err.message);
modShape[key] = shape[key];
}
}
}
return parsedTuple;
case z.ZodTypes.lazy:
var lazySchema = def.getter();
lazySchema.parse(obj, params);
return obj;
case z.ZodTypes.literal:
// const literalValue = def.value;
// if (typeof literalValue === 'object' && obj !== null) throw ZodError.fromString(`Can't process non-primitive literals.`);
// if (['string','']typeof obj === 'object') throw ZodError.fromString(`Invalid type: ${object}.`);
if (obj === def.value)
return obj;
throw ZodError_1.ZodError.fromString(obj + " !== " + def.value);
case z.ZodTypes.enum:
if (def.values.indexOf(obj) === -1) {
throw ZodError_1.ZodError.fromString("\"" + obj + "\" does not match any value in enum");
}
return obj;
// case z.ZodTypes.function:
// return obj;
default:
// function
return obj;
// assertNever(def);
// break;
return new object_1.ZodObject({
t: z.ZodTypes.object,
strict: def.strict,
shape: modShape,
});
}
}
// assertNever();
// return obj;
}; };
throw new Error("Invalid mask!\n\n" + JSON.stringify(mask, null, 2));
};
//# sourceMappingURL=masker.js.map

@@ -21,2 +21,3 @@ "use strict";

// const { seen } = params;
// const y:ZodObject<any> = "asdf" as any;
// console.log(`visit ${schemaDef.t}: ${typeof obj} - ${obj.name || ''}`);

@@ -116,4 +117,4 @@ // if (!['number', 'string', 'boolean', 'undefined'].includes(typeof obj)) {

try {
option.parse(obj, params);
return obj;
return option.parse(obj, params);
// return obj;
}

@@ -170,4 +171,4 @@ catch (err) { }

var lazySchema = def.getter();
lazySchema.parse(obj, params);
return obj;
return lazySchema.parse(obj, params);
// return obj;
case z.ZodTypes.literal:

@@ -174,0 +175,0 @@ // const literalValue = def.value;

"use strict";
// import * as z from '.';
// const Animal = z
// .object({
// species: z.string(),
// })
// .augment({
// population: z.number(),
// });
// // overwrites `species`
// const ModifiedAnimal = Animal.augment({
// species: z.array(z.string()),
// });
// ModifiedAnimal.parse({
// species: ['asd'],
// population: 1324,
// });
// ({
// population:11324,
// })
// import { util } from './types/utils';
// const fish = z.object({
// name: z.string(),
// props: z.object({
// color: z.string(),
// numScales: z.number(),
// }),
// }).augment({
// name:z.number()
// });
// type fish = z.infer<typeof fish>
// interface A {
// val: number;
// b: B;
// }
// interface B {
// val: number;
// a: A;
// }
// type TypeToShape<T> = {
// string: z.ZodString;
// number: z.ZodNumber;
// boolean: z.ZodBoolean;
// undefined: z.ZodUndefined;
// null: z.ZodNull;
// array: T extends (infer U)[] ? z.ZodArray<TypeToShape<U>> : never;
// object: z.ZodObject;
// union: z.ZodUnion;
// intersection: z.ZodIntersection;
// tuple: z.ZodTuple;
// record: z.ZodRecord;
// literal: T extends infer U ? z.ZodLiteral<U> : never;
// optional: z.ZodUnion<[z.ZodUndefined, TypeToShape<NoUndef<T>>]>;
// nullable: z.ZodUnion<[z.ZodNull, TypeToShape<NoNull<T>>]>;
// // nullable: z.ZodNull;
// // ZodFunction,
// // ZodLazy,
// // ZodEnum,
// // ZodType,
// // ZodAny,
// // ZodDef,
// // ZodError,
// }[
// // undefined extends T ?
// util.AssertEqual<T, string> extends true ? 'string' :
// util.AssertEqual<T, number> extends true ? 'number' :
// util.AssertEqual<T, boolean> extends true ? 'boolean' :
// util.AssertEqual<T, null> extends true ? 'null' :
// util.AssertEqual<T, undefined> extends true ? 'undefined' :
// never
// ]
// type StripUndefined<T> = T extends (undefined | infer U) ? U : false
// type NoUndef<T> = T extends undefined ? never : T;
// type NoNull<T> = T extends null ? never : T;
// // type adsf = NoUndef<string | undefined>
// // type lk = keyof number;
// // const fishList = z.array(fish);
// // const numList = z.array(z.string());
// // const modnumList = numList.pick(true);
// // const modFishList = fishList.pick({
// // // properties: true,
// // name:true,
// // properties: {
// // color:true
// // }
// // });
// // const modFish = fish.omit({
// // name: true,
// // });
// // const modFishList = fishList.omit({
// // name: true,
// // properties: {
// // numScales: true,
// // },
// // });
// // type nonameFish = z.infer<typeof nonameFish>;
//# sourceMappingURL=playground.js.map

@@ -56,2 +56,8 @@ "use strict";

}
// pick = <Mask extends zodmaskUtil.Params<T>>(mask: Mask): ZodArray<zodmaskUtil.pick<T, Mask>> => {
// return applyMask(this, mask, 'pick');
// };
// omit = <Mask extends zodmaskUtil.Params<T>>(mask: Mask): ZodArray<zodmaskUtil.omit<T, Mask>> => {
// return applyMask(this, mask, 'omit');
// };
ZodArray.create = function (schema) {

@@ -58,0 +64,0 @@ return new ZodArray({

@@ -36,3 +36,2 @@ import { ParseParams } from '../parser';

readonly _def: Def;
readonly _maskParams: Def;
parse: (x: Type, params?: ParseParams) => Type;

@@ -39,0 +38,0 @@ is(u: Type): u is Type;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var parser_1 = require("../parser");
// import { MaskParams, MaskedType } from './object';
// import { maskUtil } from '../helpers/maskUtil';
var ZodTypes;

@@ -29,2 +29,5 @@ (function (ZodTypes) {

var ZodType = /** @class */ (function () {
// pick = <Params extends maskUtil.Params<Type>>(_params: Params): maskUtil.Mask<Type, Params> => {
// return 'asdf' as any;
// };
// assert: zodAssertion<Type> = (value: unknown) => zodAssert(this, value);

@@ -31,0 +34,0 @@ // (u: unknown) => asserts u is Type = u => {

@@ -5,6 +5,3 @@ import * as z from './base';

import { ZodUnion } from './union';
export interface ZodShapeDef<T extends z.ZodRawShape = z.ZodRawShape> extends z.ZodTypeDef {
t: z.ZodTypes.object;
shape: T;
}
import { objectUtil } from '../helpers/objectUtil';
export interface ZodObjectDef<T extends z.ZodRawShape = z.ZodRawShape> extends z.ZodTypeDef {

@@ -15,25 +12,6 @@ t: z.ZodTypes.object;

}
declare type OptionalKeys<T extends z.ZodRawShape> = {
[k in keyof T]: undefined extends T[k]['_type'] ? k : never;
}[keyof T];
declare type RequiredKeys<T extends z.ZodRawShape> = Exclude<keyof T, OptionalKeys<T>>;
declare type ObjectIntersection<T extends z.ZodRawShape> = {
[k in OptionalKeys<T>]?: T[k]['_type'];
} & {
[k in RequiredKeys<T>]: T[k]['_type'];
};
declare type Flatten<T extends object> = {
[k in keyof T]: T[k];
};
declare type FlattenObject<T extends z.ZodRawShape> = {
[k in keyof T]: T[k];
};
declare type ObjectType<T extends z.ZodRawShape> = FlattenObject<ObjectIntersection<T>>;
declare type MergeObjectParams<First extends ZodObjectParams, Second extends ZodObjectParams> = {
strict: First['strict'] extends false ? false : Second['strict'] extends false ? false : true;
};
interface ZodObjectParams {
strict: boolean;
}
declare type ZodObjectType<T extends z.ZodRawShape, Params extends ZodObjectParams> = Params['strict'] extends true ? ObjectType<T> : Flatten<ObjectType<T> & {
declare type ZodObjectType<T extends z.ZodRawShape, Params extends ZodObjectParams> = Params['strict'] extends true ? objectUtil.ObjectType<T> : objectUtil.Flatten<objectUtil.ObjectType<T> & {
[k: string]: any;

@@ -53,5 +31,8 @@ }>;

};
nonstrict: () => ZodObject<T, Flatten<{ [k in Exclude<keyof Params, "strict">]: Params[k]; } & {
nonstrict: () => ZodObject<T, objectUtil.Flatten<{ [k in Exclude<keyof Params, "strict">]: Params[k]; } & {
strict: false;
}>>;
optional: () => ZodUnion<[this, ZodUndefined]>;
nullable: () => ZodUnion<[this, ZodNull]>;
augment: <Augmentation extends z.ZodRawShape>(augmentation: Augmentation) => ZodObject<{ [k in Exclude<keyof T, keyof Augmentation>]: T[k]; } & { [k in keyof Augmentation]: Augmentation[k]; }, Params>;
/**

@@ -62,5 +43,5 @@ * Prior to zod@1.0.12 there was a bug in the

*/
merge: <MergeShape extends z.ZodRawShape, MergeParams extends ZodObjectParams>(other: ZodObject<MergeShape, MergeParams>) => ZodObject<T & MergeShape, MergeObjectParams<Params, MergeParams>>;
optional: () => ZodUnion<[this, ZodUndefined]>;
nullable: () => ZodUnion<[this, ZodNull]>;
merge: <MergeShape extends z.ZodRawShape, MergeParams extends ZodObjectParams>(other: ZodObject<MergeShape, MergeParams>) => ZodObject<T & MergeShape, objectUtil.MergeObjectParams<Params, MergeParams>>;
pick: <Mask extends { [k in keyof T]?: true | undefined; }>(mask: Mask) => ZodObject<{ [k in keyof Mask]: k extends keyof T ? T[k] : never; }, Params>;
omit: <Mask extends { [k in keyof T]?: true | undefined; }>(mask: Mask) => ZodObject<{ [k in keyof T]: k extends keyof Mask ? never : T[k]; }, Params>;
static create: <T_1 extends z.ZodRawShape>(shape: T_1) => ZodObject<T_1, {

@@ -67,0 +48,0 @@ strict: true;

@@ -38,23 +38,3 @@ "use strict";

var union_1 = require("./union");
var intersection_1 = require("./intersection");
var mergeShapes = function (first, second) {
var firstKeys = Object.keys(first);
var secondKeys = Object.keys(second);
var sharedKeys = firstKeys.filter(function (k) { return secondKeys.indexOf(k) !== -1; });
var sharedShape = {};
for (var _i = 0, sharedKeys_1 = sharedKeys; _i < sharedKeys_1.length; _i++) {
var k = sharedKeys_1[_i];
sharedShape[k] = intersection_1.ZodIntersection.create(first[k], second[k]);
}
return __assign({}, first, second, sharedShape);
};
var mergeObjects = function (first) { return function (second) {
var mergedShape = mergeShapes(first._def.shape, second._def.shape);
var merged = new ZodObject({
t: z.ZodTypes.object,
strict: first._def.strict && second._def.strict,
shape: mergedShape,
});
return merged;
}; };
var objectUtil_1 = require("../helpers/objectUtil");
var objectDefToJson = function (def) { return ({

@@ -81,2 +61,7 @@ t: def.t,

};
_this.optional = function () { return union_1.ZodUnion.create([_this, undefined_1.ZodUndefined.create()]); };
_this.nullable = function () { return union_1.ZodUnion.create([_this, null_1.ZodNull.create()]); };
_this.augment = function (augmentation) {
return new ZodObject(__assign({}, _this._def, { shape: __assign({}, _this._def.shape, augmentation) }));
};
/**

@@ -87,13 +72,32 @@ * Prior to zod@1.0.12 there was a bug in the

*/
_this.merge = mergeObjects(_this);
_this.optional = function () { return union_1.ZodUnion.create([_this, undefined_1.ZodUndefined.create()]); };
_this.nullable = function () { return union_1.ZodUnion.create([_this, null_1.ZodNull.create()]); };
_this.merge = objectUtil_1.objectUtil.mergeObjects(_this);
_this.pick = function (mask) {
var shape = {};
Object.keys(mask).map(function (key) {
shape[key] = _this._def.shape[key];
});
return new ZodObject(__assign({}, _this._def, { shape: shape }));
};
// omitKeys = <OmitKeys extends (keyof T)[]>(...omit:OmitKeys):OmitKeys => omit;
_this.omit = function (mask) {
var shape = {};
Object.keys(_this._def.shape).map(function (key) {
if (!Object.keys(mask).includes(key)) {
shape[key] = _this._def.shape[key];
}
});
return new ZodObject(__assign({}, _this._def, { shape: shape }));
};
return _this;
// static recursion = <R extends { [k: string]: any }>() => <T extends ZodObject<any>>(
// shape: withRefsInputType<T, R>,
// ): ZodObject<withRefsReturnType<T, R>> => {
// // const getters =
// return new ZodObject({ t: z.ZodTypes.object, strict: true, shape(); });
// };
}
// pick = <Mask extends zodmaskUtil.Params<ZodObject<T>>>(
// mask: Mask,
// ): zodmaskUtil.pick<ZodObject<T, Params>, Mask> => {
// return applyMask(this, mask, 'pick');
// };
// omit = <Mask extends zodmaskUtil.Params<ZodObject<T>>>(
// mask: Mask,
// ): zodmaskUtil.omit<ZodObject<T, Params>, Mask> => {
// return applyMask(this, mask, 'omit');
// };
// relations = <Rels extends { [k: string]: any }>(

@@ -118,2 +122,8 @@ // lazyShape: { [k in keyof Rels]: ZodLazy<z.ZodType<Rels[k]>> },

// };
// static recursion = <R extends { [k: string]: any }>() => <T extends ZodObject<any>>(
// shape: withRefsInputType<T, R>,
// ): ZodObject<withRefsReturnType<T, R>> => {
// // const getters =
// return new ZodObject({ t: z.ZodTypes.object, strict: true, shape(); });
// };
ZodObject.create = function (shape) {

@@ -120,0 +130,0 @@ return new ZodObject({

"use strict";
// import { ZodStringDef } from './string';
// import { ZodNumberDef } from './number';
// import { ZodBooleanDef } from './boolean';
// import { ZodUndefinedDef } from './undefined';
// import { ZodNullDef } from './null';
// import { ZodArrayDef } from './array';
// import { ZodObjectDef } from './object';
// import { ZodUnionDef } from './union';
// import { ZodIntersectionDef } from './intersection';
// import { ZodTupleDef } from './tuple';
// import { ZodFunctionDef } from './function';
// import { ZodLazyDef } from './lazy';
// import { ZodLiteralDef } from './literal';
// import { ZodEnumDef } from './enum';
// export type ZodDef =
// | ZodStringDef
// | ZodNumberDef
// | ZodBooleanDef
// | ZodUndefinedDef
// | ZodNullDef
// | ZodArrayDef
// | ZodObjectDef
// | ZodUnionDef
// | ZodIntersectionDef
// | ZodTupleDef
// | ZodFunctionDef
// | ZodLazyDef
// | ZodLiteralDef
// | ZodEnumDef;
// // export type ZodPrimitive = ZodStr
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=utils.js.map
{
"name": "zod",
"version": "1.1.2",
"version": "1.2.0",
"description": "TypeScript-first schema declaration and validation library with static type inference",

@@ -5,0 +5,0 @@ "main": "./lib/src/index.js",

@@ -7,11 +7,12 @@ <p align="center">

[![License][license-image]][license-url]
[![npm](https://img.shields.io/npm/dw/jest-coverage-badges.svg)](https://www.npmjs.com/package/jest-coverage-badges)
![coverage](coverage/badge.svg)
[![npm](https://img.shields.io/npm/dw/zod.svg)](https://www.npmjs.com/package/zod)
[![stars](https://img.shields.io/github/stars/vriad/zod)](https://img.shields.io/github/stars/vriad/zod)
[![coverage](./coverage.svg)](./src/__tests__)
[license-url]: https://opensource.org/licenses/MIT
[license-image]: https://img.shields.io/npm/l/make-coverage-badge.svg
[license-image]: https://img.shields.io/github/license/vriad/zod
Created and maintained by [@vriad](https://twitter.com/vriad).
<br/>
Created and maintained by [@vriad](https://twitter.com/vriad). The motivation for this library and a detailed comparison to various alternatives can be found at https://vriad.com/blog/zod.
The motivation for this library and a detailed comparison to various alternatives can be found at https://vriad.com/blog/zod.
<br/>

@@ -29,6 +30,12 @@ <br/>

- [Objects](#objects)
- [.nonstrict](#unknown-keys)
- [.merge](#merging)
- [.augment](#augmentation)
- [.pick/.omit](#masking)
- [Records](#records)
- [Arrays](#arrays)
- [.nonempty](#nonempty-arrays)
- [Unions](#unions)
- [Optional types](#optional-types)
- [Nullable types](#nullable-types)
- [.optional](#optional-types)
- [.nullable](#nullable-types)
- [Enums](#enums)

@@ -39,2 +46,3 @@ - [Tuples](#tuples)

- [Function schemas](#function-schemas)
- [Masking](#masking)
- [Errors](#errors)

@@ -101,4 +109,6 @@ - [Comparison](#comparison)

Given a Zod schema, you can call its `.parse(data)` method to check `data` is valid. If it is, `data` is returned (with full type information!). Otherwise, an error is thrown.
Given a Zod schema, you can call its `.parse(data)` method to check `data` is valid. If it is, a value is returned with full type information! Otherwise, an error is thrown.
IMPORTANT: The variable you pass into `.parse` is not the same variable you get back out. Assuming the value passes validation, you get back a deep clone of the object you passed in.
```ts

@@ -140,7 +150,7 @@ const stringSchema = z.string();

You can extract the TypeScript type of any schema with `z.TypeOf<>`.
You can extract the TypeScript type of any schema with `z.infer<>`.
```ts
const A = z.string();
type A = z.TypeOf<typeof A>; // string
type A = z.infer<typeof A>; // string

@@ -162,3 +172,3 @@ const u: A = 12; // TypeError

type Dog = z.TypeOf<typeof dogSchema>;
type Dog = z.infer<typeof dogSchema>;
/*

@@ -182,3 +192,3 @@ equivalent to:

### Unknown keys
#### Unknown keys

@@ -222,3 +232,3 @@ IMPORTANT: By default, Zod object schemas _do not_ allow unknown keys.

```ts
type NonstrictDog = z.TypeOf<typeof dogSchemaNonstrict>;
type NonstrictDog = z.infer<typeof dogSchemaNonstrict>;
/*

@@ -233,2 +243,171 @@ {

#### Merging
You can combine two object schemas with `.merge`, like so:
```ts
const BaseTeacher = z.object({ subjects: z.array(z.string()) });
const HasID = z.object({ id: z.string() });
const Teacher = BaseTeacher.merge(HasId);
type Teacher = z.infer<typeof Teacher>; // => { subjects: string[], id: string }
```
You're able to fluently chain together many `.merge` calls as well:
```ts
// chaining mixins
const Teacher = BaseTeacher.merge(HasId)
.merge(HasName)
.merge(HasAddress);
```
`.merge` is just syntactic sugar over the more generic `z.intersection` which is documented below.
IMPORTANT: the schema returned by `.merge` is the _intersection_ of the two schemas. The schema passed into `.merge` does not "overwrite" properties of the original schema. To demonstrate:
```ts
const Obj1 = z.object({ field: z.string() });
const Obj2 = z.object({ field: z.number() });
const Merged = Obj1.merge(Obj2);
type Merged = z.infer<typeof merged>;
// => { field: never }
// because no type can simultaneously be both a string and a number
```
To "overwrite" existing keys, use `.augment` (documented below).
#### Augmentation
You can augment an object schema with the `.augment` method.
```ts
const Animal = z
.object({
species: z.string(),
})
.augment({
population: z.number(),
});
```
If the argument to `.augment` contains a key that already exists in the base schema, the type gets overwritten:
```ts
// overwrites `species`
const ModifiedAnimal = Animal.augment({
species: z.array(z.string()),
});
// => { population: number, species: string[] }
```
#### Masking
Object masking is one of Zod's killer features. It lets you create slight variations of your object schemas easily and succinctly.
```ts
const Recipe = z.object({
id: z.string(),
name: z.string(),
ingredients: z.array(z.string()),
});
```
Inspired by TypeScript's built-in `Pick` and `Omit` utility types, all Zod object schemas have `.pick` and `.omit` methods that return a "masked" version of the schema.
To only keep certain keys, use `.pick`.
```ts
const JustTheName = Recipe.pick({ name: true });
type JustTheName = z.infer<typeof JustTheName>; // => { name: string }
```
To remove certain keys, use `.omit`.
```ts
const NoIDRecipe = Recipe.omit({ id: true });
type NoIDRecipe = z.infer<typeof NoIDRecipe>; // => { name: string, ingredients: string[] }
```
This is useful for database logic, where endpoints often accept as input slightly modified versions of your database schemas. For instance, the input to a hypothetical `createRecipe` endpoint would accept the `NoIDRecipe` type, since the ID will be generated by your database automatically.
This is a vital feature for implementing typesafe backend logic, yet as far as I know, no other validation library (yup, Joi, io-ts, runtypes, class-validator, ow...) offers similar functionality as of this writing (April 2020). This is one of the must-have features that inspired the creation of Zod.
## Records
Records are similar to object schemas, but don't enforce a type restriction on the keys. For instance:
```ts
const objectSchema = z.object({ name: z.string() });
```
`objectSchema` only accepts objects with single key: `name`. You could use `.nonstrict()` to create a schema that accepts unknown keys, but that schema won't validated the values associated with those unknown keys.
```ts
const nonstrict = objectSchema.nonstrict();
type nonstrict = z.infer<typeof nonstrict>;
// => { name: string, [k:string]: any}
const parsed = nonstrict.parse({ name: 'Serena', bar: ['whatever'] });
parsed.bar; // no type information
```
But what if you want an object that enforces a schema on all of the values it contains? That's when you would use a record.
```ts
const User = z.object({
name: z.string(),
});
const UserStore = z.record(User);
type UserStore = z.infer<typeof UserStore>;
// => { [k: string]: { name: string } }
```
This is particularly useful for storing or caching items by ID.
```ts
const userStore: UserStore = {};
userStore['77d2586b-9e8e-4ecf-8b21-ea7e0530eadd'] = {
name: 'Carlotta',
}; // passes
userStore['77d2586b-9e8e-4ecf-8b21-ea7e0530eadd'] = {
whatever: 'Ice cream sundae',
}; // TypeError
```
And of course you can call `.parse` just like any other Zod schema.
```ts
UserStore.parse({
user_1328741234: { name: 'James' },
}); // => passes
```
#### A note on numerical keys
You may have expected `z.record()` to accept two arguments, one for the keys and one for the values. After all, TypeScript's built-in Record type does (`Record<KeyType, ValueType>`)Otherwise, how do you represent the TypeScript type `Record<number, any>` in Zod?
As it turns out, TypeScript's behavior surrounding `[k: number]` is a little unintuitive:
```ts
const testMap: { [k: number]: string } = {
1: 'one',
};
for (const key in testMap) {
console.log(`${key}: ${typeof key}`);
}
// prints: `1: string`
```
As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.
## Arrays

@@ -244,3 +423,3 @@

### Non-empty lists
#### Non-empty lists

@@ -271,3 +450,3 @@ ```ts

A.parse(undefined); // => passes, returns undefined
type A = z.TypeOf<typeof A>; // string | undefined
type A = z.infer<typeof A>; // string | undefined
```

@@ -283,3 +462,3 @@

});
type C = z.TypeOf<typeof C>; // { username?: string | undefined };
type C = z.infer<typeof C>; // { username?: string | undefined };
```

@@ -299,3 +478,3 @@

const E = z.string().nullable(); // equivalent to D
type E = z.TypeOf<typeof D>; // string | null
type E = z.infer<typeof D>; // string | null
```

@@ -320,3 +499,3 @@

type F = z.TypeOf<typeof F>; // string | number | boolean | undefined | null;
type F = z.infer<typeof F>; // string | number | boolean | undefined | null;
```

@@ -363,6 +542,6 @@

const c = z.intersection(a, b);
type c = z.TypeOf<typeof C>; // => number
type c = z.infer<typeof C>; // => number
const stringAndNumber = z.intersection(z.string(), z.number());
type Never = z.TypeOf<typeof stringAndNumber>; // => never
type Never = z.infer<typeof stringAndNumber>; // => never
```

@@ -383,25 +562,6 @@

type Teacher = z.TypeOf<typeof Teacher>;
type Teacher = z.infer<typeof Teacher>;
// { id:string; name:string };
```
### Object merging
In the examples above, the return value of `z.intersection` is an instance of `ZodIntersection`, a generic class that wraps the two schemas passed in as arguments.
But if you're trying to combine two object schemas, there is a shorthand:
```ts
const Teacher = BaseTeacher.merge(HasId);
```
The benefit of using this shorthand is that the returned value is a new object schema (`ZodObject`), instead of a generic `ZodIntersection` instance. This way, you're able to fluently chain together many `.merge` calls:
```ts
// chaining mixins
const Teacher = BaseTeacher.merge(HasId)
.merge(HasName)
.merge(HasAddress);
```
## Tuples

@@ -421,3 +581,3 @@

type Athlete = z.TypeOf<typeof athleteSchema>;
type Athlete = z.infer<typeof athleteSchema>;
// type Athlete = [string, number, { pointsScored: number }]

@@ -465,3 +625,3 @@ ```

// create an interface that extends the base schema
interface Category extends z.Infer<typeof BaseCategory> {
interface Category extends z.infer<typeof BaseCategory> {
subcategories: Category[];

@@ -512,3 +672,3 @@ }

const myFunction = z.function(args, returnType);
type myFunction = z.TypeOf<typeof myFunction>;
type myFunction = z.infer<typeof myFunction>;
// => (arg0: string)=>number

@@ -580,2 +740,74 @@ ```

<!--
## Masking
Masking is one of Zod's killer features. It sets it a step ahead of most other libraries, especially those that utilize class-based validation schemas (like TypeORM). The problem with defining schemas as a class is that it's not possible to generate slight variations of it. Doing so would require high-order generics, which doesyou would need to implement a "doubly-generic" class factory.
Consider an example where you define a `User` schema with two fields:
```ts
const User = z.object({
id: z.string(),
name: z.string(),
});
```
If you want to implement a typesafe "createUser" function, you'll need a slightly modified version of `User` as the argument. Specifically, you'll want to get rid of the `id` field, assuming your database auto-generates IDs. Historically you'd have to define a brand-new schema, say `CreateUserInput`.
If this example sounds contrived, check out the homepage of the popular GraphQL schema definition library [TypeGraphQL](https://typegraphql.com/). The sample code shows two declarations: one for the `Recipe` model and another _nearly identical_ class for `RecipeInput` (the data type used to create new recipes). Unfortunately duplicative definitions like this are commonly needed (especially in the GraphQL ecosystem), meaning you have to keep a slew of slightly modified schemas in sync manually.
Zod's solution to this is "masking". Masking is known by a lot of other names too: _derived types_, _views_ (especially in the SQL world), _projections_, and more.
### Picking
```ts
const User = z.object({
id: z.string(),
name: z.string(),
});
const createUserInput = User.pick({ name: true });
type createUserInput = z.infer<typeof createUserInput>;
// => { name: string }
```
Equivalently, you can use `.omit` to remove keys from the object schema.
```ts
const createUserInput = User.pick({ id: true });
type createUserInput = z.infer<typeof createUserInput>;
// => { name: string }
```
### Nested objects
Masking also works on nested object schemas:
```ts
const User = z.object({
outer: z.object({
prop1: z.string(),
inner: z.object({
prop2: z.number(),
}),
}),
});
// picking
User.pick({ outer: true }); // { outer: inner: { prop1: string, prop2: number }}
User.pick({ outer: { prop1: true } }); // { outer: { prop1: string }}
User.pick({ outer: { inner: true } }); // { outer: { innfer: { prop2: number }}}
User.pick({ outer: { prop1: true, inner: { prop2: true } } }); // { outer: inner: { prop1: string, prop2: number }}
// omiting
User.omit({ outer: true }); // {}
User.omit({ outer: { prop1: true } }); // { outer: { inner: { prop2: number }}}
User.omit({ outer: { inner: true } }); // { outer: { prop1: string }}
User.omit({ outer: { inner: { prop2: true } } }); // { outer: { prop1: string, inner: {} }}
```
### Recursive schemas -->
## Errors

@@ -769,3 +1001,3 @@

type C = z.TypeOf<typeof C>;
type C = z.infer<typeof C>;
// returns { foo: string; bar?: number | undefined }

@@ -772,0 +1004,0 @@ ```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc