-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Colin McDonnell
committed
Feb 8, 2023
1 parent
c8ce27e
commit e71c7be
Showing
4 changed files
with
58 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The root cause of the issue this commit is resolving is the ordering of these overloads.
writeable arrays can always be used in readonly places, but not vice versa.
When typescript is figuring out which overload to use, it checks top-to-bottom (order dependent)
If you send in a writeable version of
[U, ...U[]]
, it will still match with the top version, and use that signature, because you're saying "I will treat this as a readonly array" in the constraint, and since it doesn't matter if you don't try to write to a writeable array, typescript picks that one, and doesn't check deeper.The lower one is NEVER going to match, because all cases that will match the lower one will already have matched this top one.
This caused excessive and complex nesting in the compiled .d.ts file, once everything got transpiled. This didn't pop up in the original .ts source files because at that time, the types were inferred by the method call .create-method, which I believe might be more permissive of nesting and other typing schenanigans, but when transpiled into an explicit return type, the issue popped up, as it became the faulty
ZodEnum<Writeable<FilterEnum<T, ToExclude[number]>>>
.FilterEnum already, always, returns a writeable tuple, so it should really not go through the Writeable<> step. It would match the the writeable version of createZodEnum, which would result in a
ZodEnum<FilterEnum<T, ToExclude[number]>>
return type in the generated d.ts file, which typescript handles just fine without casting to any or other workarounds. But it doesn't even try, because it already matched the readonly version.