Created
November 8, 2023 18:33
-
-
Save alirezas/1500122bda1b1621946d65f546df8ff5 to your computer and use it in GitHub Desktop.
mini-zod from this article: https://zackoverflow.dev/writing/write-your-own-zod/
This file contains hidden or 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
interface ZodString { | |
type: "string", | |
parse(val: unknown): string | |
} | |
interface ZodNumber { | |
type: "number", | |
parse(val: unknown): number | |
} | |
interface ZodUnknown { | |
type: "unknown", | |
parse(val: unknown): unknown | |
} | |
interface ZodArray<T extends ZodType> { | |
type: "array", | |
element: T, | |
parse(val: unknown): Array<Infer<T>> | |
} | |
interface ZodObject<T extends Record<string, ZodType>> { | |
type: "object", | |
fields: T, | |
parse(val: unknown): InferZodObject<ZodObject<T>> | |
} | |
type ZodType = ZodString | ZodNumber | ZodUnknown | ZodArray<ZodType> | ZodObject<Record<string, ZodType>> | |
type InferZodObject<T extends ZodObject<Record<string, ZodType>>> = { | |
[Key in keyof T["fields"]]: Infer<T["fields"][Key]> | |
} | |
type Infer<T extends ZodType> = | |
T extends ZodUnknown ? | |
unknown : | |
T extends ZodString ? | |
string : | |
T extends ZodNumber ? | |
number : | |
T extends ZodArray<infer E> ? | |
Array<Infer<E>> : | |
T extends ZodObject<Record<string, ZodType>> ? | |
InferZodObject<T> : | |
"invalid type" | |
const string = (): ZodString => ({ | |
type: "string", | |
parse(val): string { | |
if (typeof val !== "string") throw new Error("Not a string") | |
return val | |
} | |
}) | |
const number = (): ZodNumber => ({ | |
type: "number", | |
parse(val): number { | |
if (typeof val !== "number") throw new Error("Not a number") | |
return val | |
} | |
}) | |
const unknown = (): ZodUnknown => ({ | |
type: "unknown", | |
parse(val): unknown { return val } | |
}) | |
const array = <T extends ZodType>(element: T): ZodArray<T> => ({ | |
type: "array", | |
element, | |
parse(val): Array<Infer<T>> { | |
if (!Array.isArray(val)) throw new Error("Not an array") | |
val.forEach((v) => this.element.parse(v)) | |
return val | |
} | |
}) | |
const object = <T extends Record<string, ZodType>>(fields: T): ZodObject<T> => ({ | |
type: "object", | |
fields, | |
parse(val): InferZodObject<ZodObject<T>> { | |
if (typeof val !== "object" || val == null) throw new Error("Not an object") | |
const recordVal = val as Record<string, unknown> | |
Object.entries(this.fields).forEach(([k, v]) => v.parse(recordVal[k])) | |
return val as InferZodObject<ZodObject<T>> | |
} | |
}) | |
export const z = { | |
string, | |
number, | |
unknown, | |
array, | |
object | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment