Lzh on GitHub

这份指南解释了两种我们推荐的 Valibot 命名约定,它们适用于同时创建和导出模式及推断类型的情况。

你不必遵循这些约定,它们仅供参考。

约定一

第一个命名约定是模式和类型使用相同的名称进行导出。这样做的好处是名称简短,样板代码少,因为模式和类型可以一起导入。

我们还建议遵循 PascalCase 命名约定,即每个单词的首字母都大写。这是 TypeScript 类型的常见约定,鉴于模式本质上是为类型提供运行时验证,因此对模式也使用此约定是有意义的。

示例

在下面的示例中,我们为用户对象创建一个模式。为了遵循命名约定,模式和类型使用相同的名称导出。

import * as v from 'valibot';

export const PublicUser = v.object({
  name: v.pipe(v.string(), v.maxLength(30)),
  email: v.pipe(v.string(), v.email()),
  avatar: v.nullable(v.file()),
  bio: v.pipe(v.string(), v.maxLength(1000)),
});

export type PublicUser = v.InferOutput<typeof PublicUser>;

然后,模式和类型可以一起导入和使用。

import * as v from 'valibot';
import { PublicUser } from './types';

// 将 `PublicUser` 作为类型使用
const publicUsers: PublicUser[] = [];

publicUsers.push(
  // 将 `PublicUser` 作为模式使用
  v.parse(PublicUser, {
    name: 'Jane Doe',
    email: 'jane@example.com',
    avatar: null,
    bio: 'Lorem ipsum ...',
  }),
);

约定二

第一个命名约定可能会与其他类和类型造成命名冲突。当你需要同时导出模式的输入和输出类型时,也会出现问题。

第二个命名约定提供了一个解决方案。它同样遵循 PascalCase 命名约定,但为每个导出添加了适当的后缀。模式使用 Schema 后缀,输入类型使用 Input 后缀,输出类型使用 Output 后缀。

如果输入和输出类型没有区别,可以选择使用 Data 后缀来表示。

这种约定要求模式和类型分开导入,这会增加一些开销。然而,这种命名约定更精确、灵活,并且适用于任何用例。

示例

在下面的示例中,我们为图像对象创建了一个模式。为了遵循命名约定,模式和类型使用不同的名称导出。

import * as v from 'valibot';

export const ImageSchema = v.object({
  status: v.optional(v.picklist(['public', 'private']), 'private'),
  created: v.optional(v.date(), () => new Date()),
  title: v.pipe(v.string(), v.maxLength(100)),
  source: v.pipe(v.string(), v.url()),
  size: v.pipe(v.number(), v.minValue(0)),
});

export type ImageInput = v.InferInput<typeof ImageSchema>;

export type ImageOutput = v.InferOutput<typeof ImageSchema>;

然后,模式以及输入和输出类型可以分开导入和使用。

import * as v from 'valibot';
import { ImageInput, ImageOutput, ImageSchema } from './types';

export function createImage(input: ImageInput): ImageOutput {
  return v.parse(ImageSchema, input);
}

你对改进这些约定有什么想法吗?我们欢迎你的反馈和建议。请随时在 GitHub 上创建一个 issue。