Skip to content

Commit

Permalink
Fix extract/exclude type error
Browse files Browse the repository at this point in the history
  • Loading branch information
Colin McDonnell committed Feb 8, 2023
1 parent c8ce27e commit e71c7be
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 46 deletions.
12 changes: 8 additions & 4 deletions deno/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3648,6 +3648,8 @@ export type FilterEnum<Values, ToExclude> = Values extends []
: [Head, ...FilterEnum<Rest, ToExclude>]
: never;

export type typecast<A, T> = A extends T ? A : never;

function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(
values: T,
params?: RawCreateParams
Expand Down Expand Up @@ -3724,19 +3726,21 @@ export class ZodEnum<T extends [string, ...string[]]> extends ZodType<

extract<ToExtract extends readonly [T[number], ...T[number][]]>(
values: ToExtract
) {
return ZodEnum.create(values);
): ZodEnum<Writeable<ToExtract>> {
return ZodEnum.create(values) as any;
}

exclude<ToExclude extends readonly [T[number], ...T[number][]]>(
values: ToExclude
) {
): ZodEnum<
typecast<Writeable<FilterEnum<T, ToExclude[number]>>, [string, ...string[]]>
> {
return ZodEnum.create(
this.options.filter((opt) => !values.includes(opt)) as FilterEnum<
T,
ToExclude[number]
>
);
) as any;
}

static create = createZodEnum;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zod",
"version": "3.20.4",
"version": "3.20.5",
"description": "TypeScript-first schema declaration and validation library with static type inference",
"main": "./lib/index.js",
"types": "./index.d.ts",
Expand Down
78 changes: 41 additions & 37 deletions playground.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
import { z } from "./src";
// import { z } from "./src";

const aaa = z.object({ a: z.string(), b: z.number() });
const bbb = aaa.extend({ b: z.string() });
// const arg = z.enum(["a", "b"] as const);
// const arb = arg.exclude(["b"]);
// const arc = arg.extract(["a"]);

const Type1 = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
type test1 = z.infer<typeof Type1>;
// const aaa = z.object({ a: z.string(), b: z.number() });
// const bbb = aaa.extend({ b: z.string() });

const Type2 = Type1.merge(z.object({ b: z.string() }));
type test2 = z.infer<typeof Type2>;
// const Type1 = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
// type test1 = z.infer<typeof Type1>;

const Type3 = Type2.merge(z.object({ c: z.string() }));
type test3 = z.infer<typeof Type3>;
// const Type2 = Type1.merge(z.object({ b: z.string() }));
// type test2 = z.infer<typeof Type2>;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// const arg = Type16.parse("asdf");
// arg;
12 changes: 8 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3648,6 +3648,8 @@ export type FilterEnum<Values, ToExclude> = Values extends []
: [Head, ...FilterEnum<Rest, ToExclude>]
: never;

export type typecast<A, T> = A extends T ? A : never;

function createZodEnum<U extends string, T extends Readonly<[U, ...U[]]>>(
values: T,
params?: RawCreateParams
Expand Down Expand Up @@ -3724,19 +3726,21 @@ export class ZodEnum<T extends [string, ...string[]]> extends ZodType<

extract<ToExtract extends readonly [T[number], ...T[number][]]>(
values: ToExtract
) {
return ZodEnum.create(values);
): ZodEnum<Writeable<ToExtract>> {
return ZodEnum.create(values) as any;
}

exclude<ToExclude extends readonly [T[number], ...T[number][]]>(
values: ToExclude
) {
): ZodEnum<
typecast<Writeable<FilterEnum<T, ToExclude[number]>>, [string, ...string[]]>
> {
return ZodEnum.create(
this.options.filter((opt) => !values.includes(opt)) as FilterEnum<
T,
ToExclude[number]
>
);
) as any;
}

static create = createZodEnum;
Expand Down

0 comments on commit e71c7be

Please sign in to comment.