diff --git a/README.md b/README.md index ecd04b222..78e93d914 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,9 @@ These docs have been translated into [Chinese](./README_ZH.md). - [.promise](#promise) - [.or](#or) - [.and](#and) + - [.describe](#describe) + - [.localize](#localize) + - [.name](#name) - [Guides and concepts](#guides-and-concepts) - [Type inference](#type-inference) - [Writing generic functions](#writing-generic-functions) @@ -1694,6 +1697,30 @@ const nullishString = z.string().nullish(); // string | null | undefined z.string().optional().nullable(); ``` +### `.describe` + +A schema method that adds a description to the schema for documentation purpose. + +```ts +const description = z.string().describe('usefull description').description; // string +``` + +### `.localize` + +A schema method that defines that the schema should be translated. + +```ts +const isLocalized = z.string().localize(true).localized; // boolean +``` + +### `.name` + +A schema method that defines the displayName. + +```ts +const name = z.string().name(true).displayName; +``` + ### `.array` A convenience method that returns an array schema for the given type: diff --git a/deno/lib/__tests__/localize.test.ts b/deno/lib/__tests__/localize.test.ts new file mode 100644 index 000000000..e8e8fb33e --- /dev/null +++ b/deno/lib/__tests__/localize.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("localize", () => { + const localized = true; + const schema = z.string().localize(localized); + expect(schema.localized).toEqual(localized); +}); diff --git a/deno/lib/__tests__/name.test.ts b/deno/lib/__tests__/name.test.ts new file mode 100644 index 000000000..6e1ad178f --- /dev/null +++ b/deno/lib/__tests__/name.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("name", () => { + const displayName = "myDisplayName"; + const schema = z.string().name(displayName); + expect(schema.displayName).toEqual(displayName); +}); diff --git a/deno/lib/types.ts b/deno/lib/types.ts index ee8bd6f27..a9cffae66 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -58,6 +58,8 @@ export type CustomErrorParams = Partial>; export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; + localized?: boolean; + displayName?: string; } class ParseInputLazyPath implements ParseInput { @@ -104,12 +106,26 @@ type RawCreateParams = invalid_type_error?: string; required_error?: string; description?: string; + localized?: boolean; + displayName?: string; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; +type ProcessedCreateParams = { + errorMap?: ZodErrorMap; + description?: string; + localized?: boolean; + displayName?: string; +}; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; - const { errorMap, invalid_type_error, required_error, description } = params; + const { + errorMap, + invalid_type_error, + required_error, + description, + localized, + displayName, + } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( `Can't use "invalid" or "required" in conjunction with custom error map.` @@ -124,7 +140,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description }; + return { errorMap: customMap, description, localized, displayName }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -148,6 +164,14 @@ export abstract class ZodType< return this._def.description; } + get localized() { + return this._def.localized; + } + + get displayName() { + return this._def.displayName; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -374,6 +398,8 @@ export abstract class ZodType< this.describe = this.describe.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); + this.localize = this.localize.bind(this); + this.name = this.name.bind(this); } optional(): ZodOptional { @@ -430,6 +456,22 @@ export abstract class ZodType< }); } + localize(localized: boolean): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + localized, + }); + } + + name(displayName: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + displayName, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; } diff --git a/package.json b/package.json index e48cdc607..31d1724b1 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "zod", + "name": "@mindlercare/zod", "version": "3.14.4", "description": "TypeScript-first schema declaration and validation library with static type inference", "main": "./lib/index.js", @@ -62,7 +62,8 @@ "play": "nodemon -e ts -w . -x ts-node src/playground.ts --project tsconfig.json --trace-warnings", "depcruise": "depcruise -c .dependency-cruiser.js src", "benchmark": "ts-node src/benchmarks/index.ts", - "prepare": "husky install" + "prepare": "husky install", + "postinstall": "yarn --ignore-scripts && yarn build" }, "devDependencies": { "@rollup/plugin-typescript": "^8.2.0", diff --git a/src/__tests__/localize.test.ts b/src/__tests__/localize.test.ts new file mode 100644 index 000000000..fa761be8b --- /dev/null +++ b/src/__tests__/localize.test.ts @@ -0,0 +1,10 @@ +// @ts-ignore TS6133 +import { expect, test } from "@jest/globals"; + +import * as z from "../index"; + +test("localize", () => { + const localized = true; + const schema = z.string().localize(localized); + expect(schema.localized).toEqual(localized); +}); diff --git a/src/__tests__/name.test.ts b/src/__tests__/name.test.ts new file mode 100644 index 000000000..1a8199b96 --- /dev/null +++ b/src/__tests__/name.test.ts @@ -0,0 +1,10 @@ +// @ts-ignore TS6133 +import { expect, test } from "@jest/globals"; + +import * as z from "../index"; + +test("name", () => { + const displayName = "myDisplayName"; + const schema = z.string().name(displayName); + expect(schema.displayName).toEqual(displayName); +}); diff --git a/src/types.ts b/src/types.ts index 360e7fc49..415d2f7a2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -58,6 +58,8 @@ export type CustomErrorParams = Partial>; export interface ZodTypeDef { errorMap?: ZodErrorMap; description?: string; + localized?: boolean; + displayName?: string; } class ParseInputLazyPath implements ParseInput { @@ -104,12 +106,26 @@ type RawCreateParams = invalid_type_error?: string; required_error?: string; description?: string; + localized?: boolean; + displayName?: string; } | undefined; -type ProcessedCreateParams = { errorMap?: ZodErrorMap; description?: string }; +type ProcessedCreateParams = { + errorMap?: ZodErrorMap; + description?: string; + localized?: boolean; + displayName?: string; +}; function processCreateParams(params: RawCreateParams): ProcessedCreateParams { if (!params) return {}; - const { errorMap, invalid_type_error, required_error, description } = params; + const { + errorMap, + invalid_type_error, + required_error, + description, + localized, + displayName, + } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error( `Can't use "invalid" or "required" in conjunction with custom error map.` @@ -124,7 +140,7 @@ function processCreateParams(params: RawCreateParams): ProcessedCreateParams { return { message: params.invalid_type_error }; return { message: ctx.defaultError }; }; - return { errorMap: customMap, description }; + return { errorMap: customMap, description, localized, displayName }; } export type SafeParseSuccess = { success: true; data: Output }; @@ -148,6 +164,14 @@ export abstract class ZodType< return this._def.description; } + get localized() { + return this._def.localized; + } + + get displayName() { + return this._def.displayName; + } + abstract _parse(input: ParseInput): ParseReturnType; _getType(input: ParseInput): string { @@ -374,6 +398,8 @@ export abstract class ZodType< this.describe = this.describe.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); + this.localize = this.localize.bind(this); + this.name = this.name.bind(this); } optional(): ZodOptional { @@ -430,6 +456,22 @@ export abstract class ZodType< }); } + localize(localized: boolean): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + localized, + }); + } + + name(displayName: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + displayName, + }); + } + isOptional(): boolean { return this.safeParse(undefined).success; }