Skip to content

Commit

Permalink
Add content to recursive API reference on website
Browse files Browse the repository at this point in the history
  • Loading branch information
fabian-hiller committed Jan 21, 2024
1 parent eee1c56 commit 7193cb3
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 15 deletions.
14 changes: 7 additions & 7 deletions library/src/schemas/recursive/recursive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import type { BaseSchema, Input, Output } from '../../types/index.ts';
* Recursive schema type.
*/
export type RecursiveSchema<
TSchemaGetter extends () => BaseSchema,
TOutput = Output<ReturnType<TSchemaGetter>>
> = BaseSchema<Input<ReturnType<TSchemaGetter>>, TOutput> & {
TGetter extends () => BaseSchema,
TOutput = Output<ReturnType<TGetter>>
> = BaseSchema<Input<ReturnType<TGetter>>, TOutput> & {
/**
* The schema type.
*/
type: 'recursive';
/**
* The schema getter.
*/
getter: TSchemaGetter;
getter: TGetter;
};

/**
Expand All @@ -24,9 +24,9 @@ export type RecursiveSchema<
*
* @returns A recursive schema.
*/
export function recursive<TSchemaGetter extends () => BaseSchema>(
getter: TSchemaGetter
): RecursiveSchema<TSchemaGetter> {
export function recursive<TGetter extends () => BaseSchema>(
getter: TGetter
): RecursiveSchema<TGetter> {
return {
type: 'recursive',
async: false,
Expand Down
12 changes: 6 additions & 6 deletions library/src/schemas/recursive/recursiveAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import type {
* Recursive schema async type.
*/
export type RecursiveSchemaAsync<
TSchemaGetter extends () => BaseSchema | BaseSchemaAsync,
TOutput = Output<ReturnType<TSchemaGetter>>
> = BaseSchemaAsync<Input<ReturnType<TSchemaGetter>>, TOutput> & {
TGetter extends () => BaseSchema | BaseSchemaAsync,
TOutput = Output<ReturnType<TGetter>>
> = BaseSchemaAsync<Input<ReturnType<TGetter>>, TOutput> & {
/**
* The schema type.
*/
type: 'recursive';
/**
* The schema getter.
*/
getter: TSchemaGetter;
getter: TGetter;
};

/**
Expand All @@ -30,8 +30,8 @@ export type RecursiveSchemaAsync<
* @returns An async recursive schema.
*/
export function recursiveAsync<
TSchemaGetter extends () => BaseSchema | BaseSchemaAsync
>(getter: TSchemaGetter): RecursiveSchemaAsync<TSchemaGetter> {
TGetter extends () => BaseSchema | BaseSchemaAsync
>(getter: TGetter): RecursiveSchemaAsync<TGetter> {
return {
type: 'recursive',
async: true,
Expand Down
115 changes: 114 additions & 1 deletion website/src/routes/api/(schemas)/recursive/index.mdx
Original file line number Diff line number Diff line change
@@ -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 <Link href="/api/BaseSchema/">`BaseSchema`</Link>. See the [examples](#examples) for more information.
```ts
const Schema = recursive<TGetter>(getter);
```

## Generics

- `TGetter` <Property {...properties.TGetter} />

## Parameters

- `getter` <Property {...properties.getter} />

### Explanation

The `getter` function is called lazily to retrieve the schema. This is necessary to avoid a circular dependency.

## Returns

- `Schema` <Property {...properties.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<BinaryTree> = object({
element: string(),
left: nullable(recursive(() => BinaryTreeSchema)),
right: nullable(recursive(() => BinaryTreeSchema)),
});
```

## Related

The following APIs can be combined with `recursive`.

### Schemas

<ApiList
items={[
'any',
'array',
'bigint',
'blob',
'boolean',
'date',
'enum_',
'instance',
'intersect',
'literal',
'map',
'nan',
'never',
'nonNullable',
'nonNullish',
'nonOptional',
'null_',
'nullable',
'nullish',
'number',
'object',
'optional',
'picklist',
'record',
'set',
'special',
'string',
'symbol',
'tuple',
'undefined_',
'union',
'unknown',
'variant',
'void_',
]}
/>

### Methods

<ApiList
items={[
'brand',
'coerce',
'fallback',
'getDefault',
'getDefaults',
'getFallback',
'getFallbacks',
'is',
'parse',
'safeParse',
'transform',
'unwrap',
]}
/>
35 changes: 35 additions & 0 deletions website/src/routes/api/(schemas)/recursive/properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { PropertyProps } from '~/components';

export const properties: Record<string, PropertyProps> = {
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',
},
],
},
},
};
24 changes: 24 additions & 0 deletions website/src/routes/api/(types)/RecursiveSchema/index.mdx
Original file line number Diff line number Diff line change
@@ -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` <Property {...properties.TGetter} />
- `TOutput` <Property {...properties.TOutput} />

## Definition

- `RecursiveSchema` <Property {...properties.BaseSchema} />
- `type` <Property {...properties.type} />
- `getter` <Property {...properties.getter} />
79 changes: 79 additions & 0 deletions website/src/routes/api/(types)/RecursiveSchema/properties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import type { PropertyProps } from '~/components';

export const properties: Record<string, PropertyProps> = {
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',
},
},
};
1 change: 1 addition & 0 deletions website/src/routes/api/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/)
Expand Down
2 changes: 1 addition & 1 deletion website/src/routes/guides/(schemas)/other/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const PixelStringSchema = v.special<`${number}px`>((val) =>

The <Link href="/api/recursive/">`recursive`</Link> 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 <Link href="/api/BaseSchema/">`BaseSchema`</Link>.
```ts
import * as v from 'valibot';
Expand Down

0 comments on commit 7193cb3

Please sign in to comment.