Comparing version 1.0.2 to 1.1.0
@@ -1,2 +0,2 @@ | ||
import { ValidationError, Type, StringType, NumberType, LiteralType, ObjectType, ArrayType, UnionType, PartialType, TupleType, DateType, LazyType, UndefinedType, NullType, EnumType, BooleanType, UnknownType, NumberOptions, Literal, ObjectShape, ObjectOptions, AnyType, ArrayOptions, UnionOptions, PartialOpts, IntersectionResult, DeepPartialShape, PartialShape, Eval, ToUnion, keySignature, StringTypes, OptionalType, BigIntOptions, BigIntType, StringOptions } from './types'; | ||
import { ValidationError, Type, StringType, NumberType, LiteralType, ObjectType, ArrayType, UnionType, PartialType, TupleType, DateType, LazyType, UndefinedType, NullType, EnumType, BooleanType, UnknownType, NumberOptions, Literal, ObjectShape, ObjectOptions, AnyType, ArrayOptions, UnionOptions, PartialOpts, IntersectionResult, DeepPartialShape, PartialShape, Eval, ToUnion, keySignature, StringTypes, OptionalType, BigIntOptions, BigIntType, StringOptions, EnumOptions } from './types'; | ||
export { ValidationError, Type, Infer, keySignature } from './types'; | ||
@@ -43,3 +43,3 @@ export declare const string: (opts?: StringOptions | undefined) => StringType; | ||
declare const nullValue: () => NullType; | ||
declare const enumValue: <T>(e: T) => EnumType<T>; | ||
declare const enumValue: <T>(e: T, opts?: EnumOptions<T> | undefined) => EnumType<T>; | ||
export { undefinedValue as undefined, nullValue as null, enumValue as enum }; | ||
@@ -73,3 +73,3 @@ declare const _default: { | ||
null: () => NullType; | ||
enum: <T_10>(e: T_10) => EnumType<T_10>; | ||
enum: <T_10>(e: T_10, opts?: EnumOptions<T_10> | undefined) => EnumType<T_10>; | ||
ValidationError: typeof ValidationError; | ||
@@ -76,0 +76,0 @@ keySignature: symbol; |
@@ -49,3 +49,3 @@ "use strict"; | ||
exports.null = nullValue; | ||
const enumValue = (e) => new types_1.EnumType(e); | ||
const enumValue = (e, opts) => new types_1.EnumType(e, opts); | ||
exports.enum = enumValue; | ||
@@ -52,0 +52,0 @@ // Support default imports |
@@ -128,3 +128,3 @@ export declare abstract class Type<T> { | ||
export declare class OptionalType<T extends AnyType> extends Type<Infer<T> | undefined> { | ||
private readonly schema; | ||
readonly schema: T; | ||
constructor(schema: T); | ||
@@ -238,3 +238,3 @@ parse(value: unknown, opts?: any): Infer<T> | undefined; | ||
export declare class ArrayType<T extends AnyType> extends Type<Infer<T>[]> implements WithPredicate<Infer<T>[]>, Defaultable<Infer<T>[]> { | ||
private readonly schema; | ||
readonly schema: T; | ||
private readonly predicates; | ||
@@ -287,2 +287,5 @@ private readonly defaultValue?; | ||
}; | ||
declare type UnionIntersection<U extends UnionType<any>, T extends AnyType> = U extends UnionType<infer Schemas> ? UnionType<{ | ||
[key in keyof Schemas]: Schemas[key] extends AnyType ? IntersectionResult<Schemas[key], T> : Schemas[key]; | ||
}> : never; | ||
export declare class UnionType<T extends AnyType[]> extends Type<InferTupleUnion<T>> implements Defaultable<InferTupleUnion<T>> { | ||
@@ -294,3 +297,3 @@ private readonly schemas; | ||
parse(value?: unknown): InferTupleUnion<T>; | ||
and<K extends AnyType>(schema: K): IntersectionType<this, K>; | ||
and<K extends AnyType>(schema: K): UnionIntersection<UnionType<T>, K>; | ||
default(value: InferTupleUnion<T> | (() => InferTupleUnion<T>)): UnionType<T>; | ||
@@ -307,2 +310,7 @@ } | ||
declare type ValueOf<T> = T[keyof T]; | ||
declare type EnumCoerceOptions = 'upper' | 'lower'; | ||
export declare type EnumOptions<T> = { | ||
coerce?: EnumCoerceOptions; | ||
defaultValue?: ValueOf<T> | (() => ValueOf<T>); | ||
}; | ||
export declare class EnumType<T> extends Type<ValueOf<T>> implements Defaultable<ValueOf<T>> { | ||
@@ -312,7 +320,9 @@ private readonly enumeration; | ||
private readonly defaultValue?; | ||
constructor(enumeration: T, defaultValue?: ValueOf<T> | (() => ValueOf<T>)); | ||
private readonly coerceOpt?; | ||
constructor(enumeration: T, opts?: EnumOptions<T>); | ||
parse(value?: unknown): ValueOf<T>; | ||
check(value: unknown): value is ValueOf<T>; | ||
and<K extends AnyType>(schema: K): IntersectionType<this, K>; | ||
default(value: ValueOf<T> | (() => ValueOf<T>)): EnumType<T>; | ||
default(defaultValue: ValueOf<T> | (() => ValueOf<T>)): EnumType<T>; | ||
coerce(opt: EnumCoerceOptions): EnumType<T>; | ||
} | ||
@@ -319,0 +329,0 @@ declare type DeepPartial<T> = { |
@@ -608,4 +608,23 @@ "use strict"; | ||
partial(opts) { | ||
const schema = toPartialSchema(this, { deep: (opts === null || opts === void 0 ? void 0 : opts.deep) || false }).objectShape; | ||
return new ObjectType(schema, { allowUnknown: opts === null || opts === void 0 ? void 0 : opts.allowUnknown }); | ||
const originalShape = this.objectShape; | ||
const shape = Object.keys(originalShape).reduce((acc, key) => { | ||
if (opts === null || opts === void 0 ? void 0 : opts.deep) { | ||
acc[key] = toPartialSchema(originalShape[key], opts).optional(); | ||
} | ||
else { | ||
acc[key] = originalShape[key].optional(); | ||
} | ||
return acc; | ||
}, {}); | ||
const keysig = originalShape[exports.keySignature]; | ||
if (keysig) { | ||
if (opts === null || opts === void 0 ? void 0 : opts.deep) { | ||
shape[exports.keySignature] = toPartialSchema(keysig, opts).optional(); | ||
} | ||
else { | ||
shape[exports.keySignature] = keysig.optional(); | ||
} | ||
} | ||
// Do not transfer predicates or default value to new object shape as this would not be type-safe | ||
return new ObjectType(shape, { allowUnknown: this.allowUnknown }); | ||
} | ||
@@ -852,3 +871,4 @@ shape() { | ||
and(schema) { | ||
return new IntersectionType(this, schema); | ||
const schemaIntersections = this.schemas.map(x => x.and(schema)); | ||
return new UnionType(schemaIntersections, { strict: this.strict }); | ||
} | ||
@@ -875,11 +895,7 @@ default(value) { | ||
if (this.left instanceof UnionType) { | ||
const unionSchemas = this.left.schemas; | ||
const schemas = unionSchemas.map(schema => this.right.and(schema)); | ||
const _schema = new UnionType(schemas, { strict: this.left.strict }); | ||
const _schema = this.left.and(this.right); | ||
return (value) => _schema.parse(value); | ||
} | ||
if (this.right instanceof UnionType) { | ||
const unionSchemas = this.right.schemas; | ||
const schemas = unionSchemas.map(schema => this.left.and(schema)); | ||
const _schema = new UnionType(schemas, { strict: this.right.strict }); | ||
const _schema = this.right.and(this.left); | ||
return (value) => _schema.parse(value); | ||
@@ -919,7 +935,8 @@ } | ||
class EnumType extends Type { | ||
constructor(enumeration, defaultValue) { | ||
constructor(enumeration, opts = {}) { | ||
super(); | ||
this.enumeration = enumeration; | ||
this.values = Object.values(enumeration); | ||
this.defaultValue = defaultValue; | ||
this.coerceOpt = opts.coerce; | ||
this.defaultValue = opts.defaultValue; | ||
this[exports.coercionTypeSymbol] = this.defaultValue !== undefined; | ||
@@ -930,6 +947,13 @@ } | ||
value = typeof this.defaultValue === 'function' ? this.defaultValue() : this.defaultValue) { | ||
if (!this.values.includes(value)) { | ||
let coercedValue = value; | ||
if (typeof value === 'string' && this.coerceOpt === 'lower') { | ||
coercedValue = value.toLowerCase(); | ||
} | ||
else if (typeof value === 'string' && this.coerceOpt === 'upper') { | ||
coercedValue = value.toUpperCase(); | ||
} | ||
if (!this.values.includes(coercedValue)) { | ||
throw new ValidationError(`error ${JSON.stringify(value)} not part of enum values`); | ||
} | ||
return value; | ||
return coercedValue; | ||
} | ||
@@ -942,5 +966,8 @@ check(value) { | ||
} | ||
default(value) { | ||
return new EnumType(this.enumeration, value); | ||
default(defaultValue) { | ||
return new EnumType(this.enumeration, { defaultValue }); | ||
} | ||
coerce(opt) { | ||
return new EnumType(this.enumeration, { defaultValue: this.defaultValue, coerce: opt }); | ||
} | ||
} | ||
@@ -950,22 +977,3 @@ exports.EnumType = EnumType; | ||
if (schema instanceof ObjectType) { | ||
const originalShape = schema.objectShape; | ||
const shape = Object.keys(originalShape).reduce((acc, key) => { | ||
if (opts === null || opts === void 0 ? void 0 : opts.deep) { | ||
acc[key] = toPartialSchema(originalShape[key], opts).optional(); | ||
} | ||
else { | ||
acc[key] = originalShape[key].optional(); | ||
} | ||
return acc; | ||
}, {}); | ||
const keysig = originalShape[exports.keySignature]; | ||
if (keysig) { | ||
if (opts === null || opts === void 0 ? void 0 : opts.deep) { | ||
shape[exports.keySignature] = toPartialSchema(keysig, opts).optional(); | ||
} | ||
else { | ||
shape[exports.keySignature] = keysig.optional(); | ||
} | ||
} | ||
return new ObjectType(shape, schema.opts); | ||
return schema.partial({ deep: (opts === null || opts === void 0 ? void 0 : opts.deep) || false }); | ||
} | ||
@@ -972,0 +980,0 @@ if (schema instanceof IntersectionType) { |
{ | ||
"name": "myzod", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "", | ||
@@ -28,10 +28,10 @@ "main": "./libs/index.js", | ||
"devDependencies": { | ||
"@types/mocha": "^7.0.2", | ||
"@types/node": "^14.0.5", | ||
"@types/mocha": "^8.0.1", | ||
"@types/node": "^14.0.27", | ||
"benchmonkey": "0.0.7", | ||
"mocha": "^7.2.0", | ||
"nyc": "^15.0.1", | ||
"mocha": "^8.1.1", | ||
"nyc": "^15.1.0", | ||
"prettier": "^2.0.5", | ||
"ts-node": "^8.10.1", | ||
"typescript": "^3.9.3" | ||
"ts-node": "^8.10.2", | ||
"typescript": "^3.9.7" | ||
}, | ||
@@ -38,0 +38,0 @@ "nyc": { |
@@ -135,3 +135,3 @@ # myzod | ||
const nameSchema = myzod.object({ name: myzod.string() }); | ||
const ageSchema = myzod.object({ name: myzod.number() }); | ||
const ageSchema = myzod.object({ age: myzod.number() }); | ||
@@ -688,2 +688,19 @@ const personSchema = nameSchema.and(ageSchema); // Same as ageSchema.and(nameSchema); | ||
The enum type also accepts an options object as a second parameter. | ||
You can set `coerce` to `'lower'` or `'upper'` to ignore string casing when calling `check` or `parse`. | ||
```typescript | ||
z.enum(Colors, { coerce: 'lower' }); | ||
const value: string = 'Red'; | ||
colorSchema.parse(value); | ||
// parse will return a lowercased value | ||
``` | ||
You can also set a default value in the options object. | ||
```typescript | ||
z.enum(Colors, { defaultValue: 'red' }); | ||
``` | ||
#### Date | ||
@@ -690,0 +707,0 @@ |
93470
1546
845