diff --git a/library/src/schemas/recursive/recursive.ts b/library/src/schemas/recursive/recursive.ts index 98f64f63e..aec1abae4 100644 --- a/library/src/schemas/recursive/recursive.ts +++ b/library/src/schemas/recursive/recursive.ts @@ -4,9 +4,9 @@ import type { BaseSchema, Input, Output } from '../../types/index.ts'; * Recursive schema type. */ export type RecursiveSchema< - TSchemaGetter extends () => BaseSchema, - TOutput = Output> -> = BaseSchema>, TOutput> & { + TGetter extends () => BaseSchema, + TOutput = Output> +> = BaseSchema>, TOutput> & { /** * The schema type. */ @@ -14,7 +14,7 @@ export type RecursiveSchema< /** * The schema getter. */ - getter: TSchemaGetter; + getter: TGetter; }; /** @@ -24,9 +24,9 @@ export type RecursiveSchema< * * @returns A recursive schema. */ -export function recursive BaseSchema>( - getter: TSchemaGetter -): RecursiveSchema { +export function recursive BaseSchema>( + getter: TGetter +): RecursiveSchema { return { type: 'recursive', async: false, diff --git a/library/src/schemas/recursive/recursiveAsync.ts b/library/src/schemas/recursive/recursiveAsync.ts index 14547825e..4c322b397 100644 --- a/library/src/schemas/recursive/recursiveAsync.ts +++ b/library/src/schemas/recursive/recursiveAsync.ts @@ -9,9 +9,9 @@ import type { * Recursive schema async type. */ export type RecursiveSchemaAsync< - TSchemaGetter extends () => BaseSchema | BaseSchemaAsync, - TOutput = Output> -> = BaseSchemaAsync>, TOutput> & { + TGetter extends () => BaseSchema | BaseSchemaAsync, + TOutput = Output> +> = BaseSchemaAsync>, TOutput> & { /** * The schema type. */ @@ -19,7 +19,7 @@ export type RecursiveSchemaAsync< /** * The schema getter. */ - getter: TSchemaGetter; + getter: TGetter; }; /** @@ -30,8 +30,8 @@ export type RecursiveSchemaAsync< * @returns An async recursive schema. */ export function recursiveAsync< - TSchemaGetter extends () => BaseSchema | BaseSchemaAsync ->(getter: TSchemaGetter): RecursiveSchemaAsync { + TGetter extends () => BaseSchema | BaseSchemaAsync +>(getter: TGetter): RecursiveSchemaAsync { return { type: 'recursive', async: true, diff --git a/website/src/routes/api/(schemas)/recursive/index.mdx b/website/src/routes/api/(schemas)/recursive/index.mdx index 67a6d82b6..16b2143b9 100644 --- a/website/src/routes/api/(schemas)/recursive/index.mdx +++ b/website/src/routes/api/(schemas)/recursive/index.mdx @@ -1,10 +1,123 @@ --- title: recursive +description: Creates a recursive schema. source: /schemas/recursive/recursive.ts contributors: - fabian-hiller --- +import { Link } from '@builder.io/qwik-city'; +import { ApiList, Property } from '~/components'; +import { properties } from './properties'; + # recursive -> The content of this page is not yet ready. Until then, please use the [source code](https://github.com/fabian-hiller/valibot/blob/main/library/src/schemas/recursive/recursive.ts) or take a look at [issue #287](https://github.com/fabian-hiller/valibot/issues/287) to help us extend the API reference. +Creates a recursive schema. + +> Due to a TypeScript limitation, the input and output types of recursive schemas cannot be inferred automatically. Therefore, you must explicitly specify these types using `BaseSchema`. See the [examples](#examples) for more information. + +```ts +const Schema = recursive(getter); +``` + +## Generics + +- `TGetter` + +## Parameters + +- `getter` + +### Explanation + +The `getter` function is called lazily to retrieve the schema. This is necessary to avoid a circular dependency. + +## Returns + +- `Schema` + +## Examples + +The following examples show how `recursive` can be used. + +### Binary tree schema + +Recursive schema to validate a binary tree. + +```ts +type BinaryTree = { + element: string; + left: BinaryTree | null; + right: BinaryTree | null; +}; + +const BinaryTreeSchema: BaseSchema = object({ + element: string(), + left: nullable(recursive(() => BinaryTreeSchema)), + right: nullable(recursive(() => BinaryTreeSchema)), +}); +``` + +## Related + +The following APIs can be combined with `recursive`. + +### Schemas + + + +### Methods + + diff --git a/website/src/routes/api/(schemas)/recursive/properties.ts b/website/src/routes/api/(schemas)/recursive/properties.ts new file mode 100644 index 000000000..c5bc6dd5d --- /dev/null +++ b/website/src/routes/api/(schemas)/recursive/properties.ts @@ -0,0 +1,35 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + TGetter: { + modifier: 'extends', + type: { + type: 'function', + params: [], + return: { + type: 'custom', + name: 'BaseSchema', + href: '../../types/index/', + }, + }, + }, + getter: { + type: { + type: 'custom', + name: 'TGetter', + }, + }, + Schema: { + type: { + type: 'custom', + name: 'RecursiveSchema', + href: '../RecursiveSchema/', + generics: [ + { + type: 'custom', + name: 'TGetter', + }, + ], + }, + }, +}; diff --git a/website/src/routes/api/(types)/RecursiveSchema/index.mdx b/website/src/routes/api/(types)/RecursiveSchema/index.mdx new file mode 100644 index 000000000..47b32ef9d --- /dev/null +++ b/website/src/routes/api/(types)/RecursiveSchema/index.mdx @@ -0,0 +1,24 @@ +--- +title: RecursiveSchema +description: Recursive schema type. +contributors: + - fabian-hiller +--- + +import { Property } from '~/components'; +import { properties } from './properties'; + +# RecursiveSchema + +Recursive schema type. + +## Generics + +- `TGetter` +- `TOutput` + +## Definition + +- `RecursiveSchema` + - `type` + - `getter` diff --git a/website/src/routes/api/(types)/RecursiveSchema/properties.ts b/website/src/routes/api/(types)/RecursiveSchema/properties.ts new file mode 100644 index 000000000..92d949270 --- /dev/null +++ b/website/src/routes/api/(types)/RecursiveSchema/properties.ts @@ -0,0 +1,79 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + TGetter: { + modifier: 'extends', + type: { + type: 'function', + params: [], + return: { + type: 'custom', + name: 'BaseSchema', + href: '../../types/index/', + }, + }, + }, + TOutput: { + modifier: 'extends', + type: 'any', + default: { + type: 'custom', + name: 'Output', + href: '../Output/', + generics: [ + { + type: 'custom', + name: 'ReturnType', + generics: [ + { + type: 'custom', + name: 'TGetter', + }, + ], + }, + ], + }, + }, + BaseSchema: { + type: { + type: 'custom', + name: 'BaseSchema', + href: '../BaseSchema/', + generics: [ + { + type: 'custom', + name: 'Input', + href: '../Input/', + generics: [ + { + type: 'custom', + name: 'ReturnType', + generics: [ + { + type: 'custom', + name: 'TGetter', + }, + ], + }, + ], + }, + { + type: 'custom', + name: 'TOutput', + }, + ], + }, + }, + type: { + type: { + type: 'string', + value: 'recursive', + }, + }, + getter: { + type: { + type: 'custom', + name: 'TGetter', + }, + }, +}; diff --git a/website/src/routes/api/menu.md b/website/src/routes/api/menu.md index f0bd702a4..e27763bbe 100644 --- a/website/src/routes/api/menu.md +++ b/website/src/routes/api/menu.md @@ -263,6 +263,7 @@ - [RecordOutput](/api/RecordOutput/) - [RecordPathItem](/api/RecordPathItem/) - [RecordSchema](/api/RecordSchema/) +- [RecursiveSchema](/api/RecursiveSchema/) - [SchemaResult](/api/SchemaResult/) - [SchemaWithFallback](/api/SchemaWithFallback/) - [SetPathItem](/api/SetPathItem/) diff --git a/website/src/routes/guides/(schemas)/other/index.mdx b/website/src/routes/guides/(schemas)/other/index.mdx index 8402f64ca..fb986262c 100644 --- a/website/src/routes/guides/(schemas)/other/index.mdx +++ b/website/src/routes/guides/(schemas)/other/index.mdx @@ -54,7 +54,7 @@ const PixelStringSchema = v.special<`${number}px`>((val) => The `recursive` schema function allows you to define recursive schemas. A recursive schema is a schema that references itself. For example, you can use it to define a schema for a tree-like data structure. -> Due to a TypeScript limitation, the input and output types cannot be inferred automatically. Therefore, you must explicitly specify these types using `BaseSchema`. +> Due to a TypeScript limitation, the input and output types cannot be inferred automatically. Therefore, you must explicitly specify these types using `BaseSchema`. ```ts import * as v from 'valibot';