Comparing version 0.0.28 to 0.0.29
@@ -1,2 +0,2 @@ | ||
declare abstract class Type<T> { | ||
export declare abstract class Type<T> { | ||
constructor(); | ||
@@ -69,3 +69,3 @@ abstract parse(value: unknown): T; | ||
constructor(schema: T); | ||
parse(value: unknown): Infer<T> | undefined; | ||
parse(value: unknown, opts?: any): Infer<T> | undefined; | ||
} | ||
@@ -199,2 +199,7 @@ declare class NullableType<T extends AnyType> extends Type<Infer<T> | null> { | ||
} | ||
declare class LazyType<T extends () => AnyType> extends Type<Infer<ReturnType<T>>> { | ||
private readonly fn; | ||
constructor(fn: T); | ||
parse(value: unknown, opts?: PathOptions): Infer<ReturnType<T>>; | ||
} | ||
export declare const string: (opts?: Partial<{ | ||
@@ -231,2 +236,3 @@ pattern: RegExp; | ||
export declare const date: () => DateType; | ||
export declare const lazy: <T extends () => AnyType>(fn: T) => LazyType<T>; | ||
declare const undefinedValue: () => UndefinedType; | ||
@@ -237,2 +243,3 @@ declare const nullValue: () => NullType; | ||
declare const _default: { | ||
Type: typeof Type; | ||
string: (opts?: Partial<{ | ||
@@ -239,0 +246,0 @@ pattern: RegExp; |
@@ -18,2 +18,3 @@ "use strict"; | ||
} | ||
exports.Type = Type; | ||
class ValidationError extends Error { | ||
@@ -51,3 +52,2 @@ constructor(message, path) { | ||
const allowUnknownSymbol = Symbol.for('allowUnknown'); | ||
const requiredKeysSymbol = Symbol.for('requiredKeys'); | ||
const shapekeysSymbol = Symbol.for('shapeKeys'); | ||
@@ -197,7 +197,8 @@ const coercionTypeSybol = Symbol.for('coersion'); | ||
} | ||
parse(value) { | ||
parse(value, opts) { | ||
if (value === undefined) { | ||
return undefined; | ||
} | ||
return this.schema.parse(value); | ||
//@ts-ignore | ||
return this.schema.parse(value, opts); | ||
} | ||
@@ -248,9 +249,2 @@ } | ||
this[shapekeysSymbol] = keys; | ||
this[requiredKeysSymbol] = keys.filter(key => { | ||
const keySchema = this.objectShape[key]; | ||
const isUndefined = keySchema instanceof UndefinedType; | ||
const unionOfUndefined = keySchema instanceof UnionType && | ||
keySchema.schemas.some((schema) => schema instanceof UndefinedType); | ||
return !isUndefined && !unionOfUndefined; | ||
}); | ||
this[coercionTypeSybol] = Object.values(this.objectShape).some(schema => schema[coercionTypeSybol]); | ||
@@ -282,3 +276,2 @@ } | ||
} | ||
//@ts-ignore | ||
const convVal = this[coercionTypeSybol] ? (allowUnknown ? Object.assign({}, value) : {}) : undefined; | ||
@@ -292,16 +285,6 @@ for (const key of keys) { | ||
if (convVal) { | ||
if (schema instanceof ObjectType || schema instanceof ArrayType || schema instanceof RecordType) { | ||
convVal[key] = schema.parse(value[key], { suppressPathErrMsg: true }); | ||
} | ||
else { | ||
convVal[key] = schema.parse(value[key]); | ||
} | ||
convVal[key] = schema.parse(value[key], { suppressPathErrMsg: true }); | ||
} | ||
else { | ||
if (schema instanceof ObjectType || schema instanceof ArrayType || schema instanceof RecordType) { | ||
schema.parse(value[key], { suppressPathErrMsg: true }); | ||
} | ||
else { | ||
schema.parse(value[key]); | ||
} | ||
schema.parse(value[key], { suppressPathErrMsg: true }); | ||
} | ||
@@ -386,3 +369,3 @@ } | ||
this._parse = | ||
this.schema instanceof ObjectType || this.schema instanceof ArrayType | ||
this.schema instanceof ObjectType || this.schema instanceof ArrayType || this.schema instanceof LazyType | ||
? (elem) => this.schema.parse(elem, { suppressPathErrMsg: true }) | ||
@@ -513,6 +496,2 @@ : (elem) => this.schema.parse(elem); | ||
this[allowUnknownSymbol] = !!(this.left[allowUnknownSymbol] || this.right[allowUnknownSymbol]); | ||
if (this.left[requiredKeysSymbol] && this.right[requiredKeysSymbol]) { | ||
//@ts-ignore | ||
this[requiredKeysSymbol] = Array.from(new Set([...this.left[requiredKeysSymbol], ...this.right[requiredKeysSymbol]])); | ||
} | ||
if (this.left[shapekeysSymbol] && this.right[shapekeysSymbol]) { | ||
@@ -536,3 +515,2 @@ //@ts-ignore | ||
if (this.left instanceof RecordType && this.right instanceof ObjectType) { | ||
this[requiredKeysSymbol] = this.right[requiredKeysSymbol]; | ||
//@ts-ignore | ||
@@ -542,3 +520,2 @@ return (value) => this.parseRecordObjectIntersection(value, this.left, this.right); | ||
if (this.right instanceof RecordType && this.left instanceof ObjectType) { | ||
this[requiredKeysSymbol] = this.left[requiredKeysSymbol]; | ||
//@ts-ignore | ||
@@ -549,7 +526,5 @@ return (value) => this.parseRecordObjectIntersection(value, this.right, this.left); | ||
if (this.left instanceof PartialType) { | ||
this[requiredKeysSymbol] = this.right[requiredKeysSymbol]; | ||
return (value) => new IntersectionType(this.left.schema, this.right).parse(value); | ||
} | ||
if (this.right instanceof PartialType) { | ||
this[requiredKeysSymbol] = this.left[requiredKeysSymbol]; | ||
return (value) => new IntersectionType(this.left, this.right.schema).parse(value); | ||
@@ -809,2 +784,17 @@ } | ||
} | ||
class LazyType extends Type { | ||
constructor(fn) { | ||
super(); | ||
this.fn = fn; | ||
// Since we can't know what the schema is we can't assume its not a coersionType and we need to disable the optimization | ||
this[coercionTypeSybol] = true; | ||
} | ||
parse(value, opts) { | ||
const schema = this.fn(); | ||
if ((opts === null || opts === void 0 ? void 0 : opts.suppressPathErrMsg) && schema instanceof ObjectType) { | ||
return schema.parse(value, opts); | ||
} | ||
return schema.parse(value); | ||
} | ||
} | ||
exports.string = (opts) => new StringType(opts); | ||
@@ -826,2 +816,3 @@ exports.boolean = () => new BooleanType(); | ||
exports.date = () => new DateType(); | ||
exports.lazy = (fn) => new LazyType(fn); | ||
const undefinedValue = () => new UndefinedType(); | ||
@@ -835,2 +826,3 @@ exports.undefined = undefinedValue; | ||
exports.default = { | ||
Type, | ||
string: exports.string, | ||
@@ -837,0 +829,0 @@ boolean: exports.boolean, |
{ | ||
"name": "myzod", | ||
"version": "0.0.28", | ||
"version": "0.0.29", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "./libs/index.js", |
@@ -91,2 +91,6 @@ # myzod | ||
Recursive Schemas | ||
- [lazy](#lazy) | ||
### myzod.Type<T> | ||
@@ -546,1 +550,17 @@ | ||
``` | ||
#### Lazy | ||
The myzod.lazy function takes a function that returns a schema and lazily evaluates it at parse. The advantage with this approach is that you can create schemas that reference themselves. Unfortunately typescript cannot resolve this type and it will be the user's responsibility to provide the corresponding myzod type. Fortunately if the user's provided type is incompatible with the given schema it will fail to compile so there is some hope. | ||
```typescript | ||
type Person = { | ||
name: string; | ||
friends: Person[]; | ||
}; | ||
const personSchema: z.Type<Person> = myzod.object({ | ||
name: myzod.string(), | ||
friends: myzod.array(myzod.lazy(() => personSchema)), | ||
}); | ||
``` |
61544
565
1134