From e2389b0312fb1b280a90d4bd1f10d099178aec9a Mon Sep 17 00:00:00 2001 From: Colin McDonnell <colinmcd@alum.mit.edu> Date: Sun, 24 Oct 2021 14:16:04 -0400 Subject: [PATCH] Add describe --- README.md | 8 ++++++-- coverage.svg | 2 +- deno/lib/__tests__/description.test.ts | 11 +++++++++++ deno/lib/types.ts | 16 +++++++++++++++- package.json | 2 +- src/__tests__/description.test.ts | 10 ++++++++++ src/types.ts | 16 +++++++++++++++- 7 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 deno/lib/__tests__/description.test.ts create mode 100644 src/__tests__/description.test.ts diff --git a/README.md b/README.md index 3ef8b5058..696b94386 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,14 @@ </p> <p align="center"> -⭐️ smash that star button ⭐️ +by [@colinhacks](https://twitter.com/colinhacks) </p> -> Like typesafety? Check out [tRPC](https://trpc.io) — a better way to build end-to-end typesafe APIs without GraphQL or code generation — just TypeScript. +> Hi! Colin here, creator of Zod. I hope you find it easy to use and powerful enough for all your use cases. If you have any issues or suggestions, please [open an issue](https://github.com/colinhacks/zod/issues/new)! +> +> If you like typesafety, check out my other library [tRPC](https://trpc.io). It works in concert with Zod to provide a seamless way to build end-to-end typesafe APIs without GraphQL or code generation — just TypeScript. +> +> Colin (AKA [@colinhacks](https://twitter.com/colinhacks)) <br/> diff --git a/coverage.svg b/coverage.svg index d77838c30..297acbbf9 100644 --- a/coverage.svg +++ b/coverage.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 95.79%"><title>Coverage: 95.79%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#4c1"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">95.79%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">95.79%</text></g></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="110" height="20" role="img" aria-label="Coverage: 95.8%"><title>Coverage: 95.8%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="110" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="47" height="20" fill="#4c1"/><rect width="110" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="855" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">95.8%</text><text x="855" y="140" transform="scale(.1)" fill="#fff" textLength="370">95.8%</text></g></svg> \ No newline at end of file diff --git a/deno/lib/__tests__/description.test.ts b/deno/lib/__tests__/description.test.ts new file mode 100644 index 000000000..d10e60b61 --- /dev/null +++ b/deno/lib/__tests__/description.test.ts @@ -0,0 +1,11 @@ +// @ts-ignore TS6133 +import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts"; +const test = Deno.test; + +import * as z from "../index.ts"; + +test("description", () => { + const schema: any = z.string(); + const DESC = "asdlfkjasdf"; + expect(schema.describe(DESC).description).toEqual(DESC); +}); diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 889723997..0b889fd39 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -54,6 +54,7 @@ export type { TypeOf as infer }; export type CustomErrorParams = Partial<util.Omit<ZodCustomIssue, "code">>; export interface ZodTypeDef { errorMap?: ZodErrorMap; + description?: string; } const handleResult = <Input, Output>( @@ -78,9 +79,10 @@ type RawCreateParams = errorMap?: ZodErrorMap; invalid_type_error?: string; required_error?: string; + description?: string; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap }; +type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; if (params.errorMap && (params.invalid_type_error || params.required_error)) { @@ -110,6 +112,10 @@ export abstract class ZodType< readonly _input!: Input; readonly _def!: Def; + get description() { + return this._def.description; + } + abstract _parse(input: ParseInput): ParseReturnType<Output>; _processInputParams( @@ -336,6 +342,14 @@ export abstract class ZodType< }) as any; } + describe(description: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + description, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } diff --git a/package.json b/package.json index a9b4f151b..bc3f3b04a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zod", - "version": "3.11.2", + "version": "3.11.4", "description": "TypeScript-first schema declaration and validation library with static type inference", "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/src/__tests__/description.test.ts b/src/__tests__/description.test.ts new file mode 100644 index 000000000..9c2f7286c --- /dev/null +++ b/src/__tests__/description.test.ts @@ -0,0 +1,10 @@ +// @ts-ignore TS6133 +import { expect, test } from "@jest/globals"; + +import * as z from "../index"; + +test("description", () => { + const schema: any = z.string(); + const DESC = "asdlfkjasdf"; + expect(schema.describe(DESC).description).toEqual(DESC); +}); diff --git a/src/types.ts b/src/types.ts index be5a030b0..020eaccec 100644 --- a/src/types.ts +++ b/src/types.ts @@ -54,6 +54,7 @@ export type { TypeOf as infer }; export type CustomErrorParams = Partial<util.Omit<ZodCustomIssue, "code">>; export interface ZodTypeDef { errorMap?: ZodErrorMap; + description?: string; } const handleResult = <Input, Output>( @@ -78,9 +79,10 @@ type RawCreateParams = errorMap?: ZodErrorMap; invalid_type_error?: string; required_error?: string; + description?: string; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap }; +type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; if (params.errorMap && (params.invalid_type_error || params.required_error)) { @@ -110,6 +112,10 @@ export abstract class ZodType< readonly _input!: Input; readonly _def!: Def; + get description() { + return this._def.description; + } + abstract _parse(input: ParseInput): ParseReturnType<Output>; _processInputParams( @@ -336,6 +342,14 @@ export abstract class ZodType< }) as any; } + describe(description: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + description, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; }