Skip to content

Commit

Permalink
Revert merge changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Colin McDonnell committed Feb 8, 2023
1 parent b8d731f commit 06c237c
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 138 deletions.
8 changes: 4 additions & 4 deletions deno/lib/__tests__/catch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test("catch with transform", () => {
);

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string>(true);
});
Expand All @@ -64,7 +64,7 @@ test("catch on existing optional", () => {
);

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
Expand All @@ -73,7 +73,7 @@ test("optional on catch", () => {
const stringWithDefault = z.string().catch("asdf").optional();

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
Expand Down Expand Up @@ -107,7 +107,7 @@ test("nested", () => {
inner: "asdf",
});
type input = z.input<typeof outer>;
util.assertEqual<input, { inner: string }>(true);
util.assertEqual<input, unknown>(true);
type out = z.output<typeof outer>;
util.assertEqual<out, { inner: string }>(true);
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
Expand Down
4 changes: 3 additions & 1 deletion deno/lib/__tests__/object.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,9 @@ test("inferred merged object type with optional properties", async () => {
.object({ a: z.string(), b: z.string().optional() })
.merge(z.object({ a: z.string().optional(), b: z.string() }));
type Merged = z.infer<typeof Merged>;
util.assertEqual<Merged, { a?: string; b: string }>(true);
util.assertEqual<Merged, { a: string | undefined; b: string }>(true);
// todo
// util.assertEqual<Merged, { a?: string; b: string }>(true);
});

test("inferred unioned object type with optional properties", async () => {
Expand Down
162 changes: 126 additions & 36 deletions deno/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1849,25 +1849,7 @@ export namespace objectUtil {
};
}

export type extendShape<A, B> = Omit<A, keyof B> & B;

const AugmentFactory =
<Def extends ZodObjectDef>(def: Def) =>
<Augmentation extends ZodRawShape>(
augmentation: Augmentation
): ZodObject<
extendShape<ReturnType<Def["shape"]>, Augmentation>,
Def["unknownKeys"],
Def["catchall"]
> => {
return new ZodObject({
...def,
shape: () => ({
...def.shape(),
...augmentation,
}),
}) as any;
};
export type extendShape<A, B> = util.flatten<Omit<A, keyof B> & B>;

export type UnknownKeysParam = "passthrough" | "strict" | "strip";

Expand All @@ -1882,18 +1864,27 @@ export interface ZodObjectDef<
unknownKeys: UnknownKeys;
}

export type mergeTypes<A, B> = {
[k in keyof A | keyof B]: k extends keyof B
? B[k]
: k extends keyof A
? A[k]
: never;
};

export type processType<T extends object> = util.flatten<
objectUtil.addQuestionMarks<T>
>;
export type baseObjectOutputType<Shape extends ZodRawShape> =
objectUtil.flatten<
objectUtil.addQuestionMarks<{
[k in keyof Shape]: Shape[k]["_output"];
}>
>;
objectUtil.addQuestionMarks<{
[k in keyof Shape]: Shape[k]["_output"];
}>;

export type objectOutputType<
Shape extends ZodRawShape,
Catchall extends ZodTypeAny
> = ZodTypeAny extends Catchall
? baseObjectOutputType<Shape>
? objectUtil.flatten<baseObjectOutputType<Shape>>
: objectUtil.flatten<
baseObjectOutputType<Shape> & { [k: string]: Catchall["_output"] }
>;
Expand Down Expand Up @@ -2128,28 +2119,99 @@ export class ZodObject<
*/
nonstrict = this.passthrough;

augment = AugmentFactory<ZodObjectDef<T, UnknownKeys, Catchall>>(this._def);
extend = AugmentFactory<ZodObjectDef<T, UnknownKeys, Catchall>>(this._def);
// augment = AugmentFactory<ZodObjectDef<T, UnknownKeys, Catchall>>(this._def);
// extend = AugmentFactory<ZodObjectDef<T, UnknownKeys, Catchall>>(this._def);
extend<
Augmentation extends ZodRawShape,
// NewShape extends extendShape<T, Augmentation>,
// OldOutput = util.flatten<Omit<Output, keyof Augmentation>>,
// AugOutput = baseObjectOutputType<Augmentation>,
// NewOutput = OldOutput & AugOutput,
NewOutput extends util.flatten<{
[k in keyof Augmentation | keyof Output]: k extends keyof Augmentation
? Augmentation[k]["_output"]
: k extends keyof Output
? Output[k]
: never;
}>,
// OldInput = util.flatten<Omit<Input, keyof Augmentation>>,
// AugInput = baseObjectInputType<Augmentation>,
// NewInput = OldInput & AugInput
NewInput extends util.flatten<{
[k in keyof Augmentation | keyof Input]: k extends keyof Augmentation
? Augmentation[k]["_input"]
: k extends keyof Input
? Input[k]
: never;
}>
// AKeys extends string | number | symbol = keyof Augmentation,

setKey<Key extends string, Schema extends ZodTypeAny>(
key: Key,
schema: Schema
): ZodObject<T & { [k in Key]: Schema }, UnknownKeys, Catchall> {
return this.augment({ [key]: schema }) as any;
// AKeys extends string | number | symbol = keyof Augmentation
>(
augmentation: Augmentation
): ZodObject<
extendShape<T, Augmentation>,
UnknownKeys,
Catchall,
NewOutput,
NewInput
> {
return new ZodObject({
...this._def,
shape: () => ({
...this._def.shape(),
...augmentation,
}),
}) as any;
}
/**
* @deprecated Use `.extend` instead
* */
augment = this.extend;

/**
* Prior to zod@1.0.12 there was a bug in the
* inferred type of merged objects. Please
* upgrade if you are experiencing issues.
*/
merge<Incoming extends AnyZodObject>(
// merge<Incoming extends AnyZodObject>(merging: Incoming) {
// return this.extend(merging.shape as Incoming["shape"]);
// }
merge<
Incoming extends AnyZodObject,
Augmentation extends Incoming["shape"],
// NewShape extends extendShape<T, Augmentation>,
// OldOutput = util.flatten<Omit<Output, keyof Augmentation>>,
// AugOutput = baseObjectOutputType<Augmentation>,
// NewOutput = OldOutput & AugOutput,
NewOutput extends {
[k in keyof Augmentation | keyof Output]: k extends keyof Augmentation
? Augmentation[k]["_output"]
: k extends keyof Output
? Output[k]
: never;
},
// OldInput = util.flatten<Omit<Input, keyof Augmentation>>,
// AugInput = baseObjectInputType<Augmentation>,
// NewInput = OldInput & AugInput
NewInput extends {
[k in keyof Augmentation | keyof Input]: k extends keyof Augmentation
? Augmentation[k]["_input"]
: k extends keyof Input
? Input[k]
: never;
}
// AKeys extends string | number | symbol = keyof Augmentation,

// AKeys extends string | number | symbol = keyof Augmentation
>(
merging: Incoming
): //ZodObject<T & Incoming["_shape"], UnknownKeys, Catchall> = (merging) => {
ZodObject<
): ZodObject<
extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
Incoming["_def"]["unknownKeys"],
Incoming["_def"]["catchall"]
Incoming["_def"]["catchall"],
NewOutput,
NewInput
> {
// const mergedShape = objectUtil.mergeShapes(
// this._def.shape(),
Expand All @@ -2165,6 +2227,34 @@ export class ZodObject<
return merged;
}

setKey<Key extends string, Schema extends ZodTypeAny>(
key: Key,
schema: Schema
): ZodObject<T & { [k in Key]: Schema }, UnknownKeys, Catchall> {
return this.augment({ [key]: schema }) as any;
}
// merge<Incoming extends AnyZodObject>(
// merging: Incoming
// ): //ZodObject<T & Incoming["_shape"], UnknownKeys, Catchall> = (merging) => {
// ZodObject<
// extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
// Incoming["_def"]["unknownKeys"],
// Incoming["_def"]["catchall"]
// > {
// // const mergedShape = objectUtil.mergeShapes(
// // this._def.shape(),
// // merging._def.shape()
// // );
// const merged: any = new ZodObject({
// unknownKeys: merging._def.unknownKeys,
// catchall: merging._def.catchall,
// shape: () =>
// objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),
// typeName: ZodFirstPartyTypeKind.ZodObject,
// }) as any;
// return merged;
// }

catchall<Index extends ZodTypeAny>(
index: Index
): ZodObject<T, UnknownKeys, Index> {
Expand Down
62 changes: 50 additions & 12 deletions playground.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
import { z } from "./src";

const schema = z.object({
a: z.string(),
b: z.string().catch("b"),
});
const aaa = z.object({ a: z.string(), b: z.number() });
const bbb = aaa.extend({ b: z.string() });

const result = schema.safeParse({
a: {},
b: 3,
});
const Type1 = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
type test1 = z.infer<typeof Type1>;

console.log(result);
const Type2 = Type1.merge(z.object({ b: z.string() }));
type test2 = z.infer<typeof Type2>;

const r = z.any().transform((val) => String(val));
type In = z.input<typeof r>;
type Out = z.output<typeof r>;
const Type3 = Type2.merge(z.object({ c: z.string() }));
type test3 = z.infer<typeof Type3>;

const Type4 = Type3.merge(z.object({ Type3: z.string() }));
type test4 = z.infer<typeof Type4>;

const Type5 = Type4.merge(z.object({ Type4: z.string() }));
type test5 = z.infer<typeof Type5>;

const Type6 = Type5.merge(z.object({ Type5: z.string() }));
type test6 = z.infer<typeof Type6>;

const Type7 = Type6.merge(z.object({ Type6: z.string() }));
type test7 = z.infer<typeof Type7>;

const Type8 = Type7.merge(z.object({ Type7: z.string() }));
type test8 = z.infer<typeof Type8>;

const Type9 = Type8.merge(z.object({ Type8: z.string() }));
type test9 = z.infer<typeof Type9>;

const Type10 = Type9.merge(z.object({ Type9: z.string() }));
type test10 = z.infer<typeof Type10>;

const Type11 = Type10.merge(z.object({ Type10: z.string() }));
type test11 = z.infer<typeof Type11>;

const Type12 = Type11.merge(z.object({ Type11: z.string() }));
type test12 = z.infer<typeof Type12>;

const Type13 = Type12.merge(z.object({ Type12: z.string() }));
type test13 = z.infer<typeof Type13>;

const Type14 = Type13.merge(z.object({ Type13: z.string() }));
type test14 = z.infer<typeof Type14>;

const Type15 = Type14.merge(z.object({ Type14: z.string() }));
type test15 = z.infer<typeof Type15>;

const Type16 = Type14.merge(z.object({ Type15: z.string() }));
type test16 = z.infer<typeof Type16>;

const arg = Type16.parse("asdf");
arg;
8 changes: 4 additions & 4 deletions src/__tests__/catch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test("catch with transform", () => {
);

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string>(true);
});
Expand All @@ -63,7 +63,7 @@ test("catch on existing optional", () => {
);

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
Expand All @@ -72,7 +72,7 @@ test("optional on catch", () => {
const stringWithDefault = z.string().catch("asdf").optional();

type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
Expand Down Expand Up @@ -106,7 +106,7 @@ test("nested", () => {
inner: "asdf",
});
type input = z.input<typeof outer>;
util.assertEqual<input, { inner: string }>(true);
util.assertEqual<input, unknown>(true);
type out = z.output<typeof outer>;
util.assertEqual<out, { inner: string }>(true);
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
Expand Down
Loading

0 comments on commit 06c237c

Please sign in to comment.