Zod:使用现有类型创建模式
Zod: create a schema using an existing type
我有一个端点应该得到一个参数 method
,它应该符合 axios 类型 Method
。
我如何在 Zod 中创建一个模式来验证值使用的类型是 Schema
?
import { Method } from 'axios';
const Schema = zod.object({
method: zod.someHowUseTheTypeFrom(Method),
});
axios 包中 Method
的类型是:
export type Method =
| 'get' | 'GET'
| 'delete' | 'DELETE'
| 'head' | 'HEAD'
| 'options' | 'OPTIONS'
| 'post' | 'POST'
| 'put' | 'PUT'
| 'patch' | 'PATCH'
| 'purge' | 'PURGE'
| 'link' | 'LINK'
| 'unlink' | 'UNLINK'
如果你想直接使用类型你可以使用这个:
const methods = ['get','GET',...] as const;
export type Method = (typeof methods)[number];
zod.enum(methods);
通过这种方式,您可以两全其美;在您可以使用的值(数组)和您最初想要的类型中使用这些方法。
阅读您的评论,您似乎想确保您的架构与 axios 中的 Method
类型同步。我建议执行以下操作:
import { z } from 'zod';
import type { Method } from 'axios';
const methods: z.ZodType<Method> = z.enum(['get', 'GET', ...]);
这至少会强制表达式右侧的模式解析有效的 axios Method
结果。不幸的是,除非 axios
还导出一个数组,其中包含与 Method
类型中的值相对应的字符串,否则可能无法实现更多。
您正在寻找的原始内容 z.something(<type here>)
无法工作,因为 zod 使用实际的运行时对象,并且像 Method
这样的类型在运行时不存在。如果 axios
导出了一个包含这些方法的数组,那么 将 是一个运行时值,您可以使用它(可能使用某种类型转换)来生成您的 methods
架构(稍后详细介绍)。
这种方法的另一个缺点是像这样的东西会进行类型检查:
const methods z.ZodType<Method> = z.enum(['get']);
这是因为类型在 TypeScript 中的工作方式。该 enum
模式只会为 'get'
成功解析,但由于文字 'get'
是 Method
中定义的较大联合类型的子类型,因此生成的模式也是可分配的。
因此,我要提出的下一个选项感觉有点 self-defeating,因为它需要重新声明 Method
中的所有值,但是,您可以继续使用 axios
Method
类型,你肯定会有一个模式来解析 Method
中的所有值(即,不会屈服于上述问题):
import { z } from "zod";
import { Method } from "axios";
const METHOD_MAP: { [K in Method]: null } = {
get: null,
GET: null,
delete: null,
DELETE: null,
head: null,
HEAD: null,
options: null,
OPTIONS: null,
post: null,
POST: null,
put: null,
PUT: null,
patch: null,
PATCH: null,
purge: null,
PURGE: null,
link: null,
LINK: null,
unlink: null,
UNLINK: null
};
const METHODS = (Object.keys(METHOD_MAP) as unknown) as readonly [
Method,
...Method[]
];
const methods: z.ZodType<Method> = z.enum(METHODS);
METHODS
的类型断言在这里是安全的,因为 METHODS_MAP
没有导出,我们确切地知道它有什么键。现在,如果缺少任何 Method
值,METHOD_MAP
对象将导致类型错误,这意味着生成的模式将解析所有 Method
值作为编译时强制执行的保证。
我有一个端点应该得到一个参数 method
,它应该符合 axios 类型 Method
。
我如何在 Zod 中创建一个模式来验证值使用的类型是 Schema
?
import { Method } from 'axios';
const Schema = zod.object({
method: zod.someHowUseTheTypeFrom(Method),
});
axios 包中 Method
的类型是:
export type Method =
| 'get' | 'GET'
| 'delete' | 'DELETE'
| 'head' | 'HEAD'
| 'options' | 'OPTIONS'
| 'post' | 'POST'
| 'put' | 'PUT'
| 'patch' | 'PATCH'
| 'purge' | 'PURGE'
| 'link' | 'LINK'
| 'unlink' | 'UNLINK'
如果你想直接使用类型你可以使用这个:
const methods = ['get','GET',...] as const;
export type Method = (typeof methods)[number];
zod.enum(methods);
通过这种方式,您可以两全其美;在您可以使用的值(数组)和您最初想要的类型中使用这些方法。
阅读您的评论,您似乎想确保您的架构与 axios 中的 Method
类型同步。我建议执行以下操作:
import { z } from 'zod';
import type { Method } from 'axios';
const methods: z.ZodType<Method> = z.enum(['get', 'GET', ...]);
这至少会强制表达式右侧的模式解析有效的 axios Method
结果。不幸的是,除非 axios
还导出一个数组,其中包含与 Method
类型中的值相对应的字符串,否则可能无法实现更多。
您正在寻找的原始内容 z.something(<type here>)
无法工作,因为 zod 使用实际的运行时对象,并且像 Method
这样的类型在运行时不存在。如果 axios
导出了一个包含这些方法的数组,那么 将 是一个运行时值,您可以使用它(可能使用某种类型转换)来生成您的 methods
架构(稍后详细介绍)。
这种方法的另一个缺点是像这样的东西会进行类型检查:
const methods z.ZodType<Method> = z.enum(['get']);
这是因为类型在 TypeScript 中的工作方式。该 enum
模式只会为 'get'
成功解析,但由于文字 'get'
是 Method
中定义的较大联合类型的子类型,因此生成的模式也是可分配的。
因此,我要提出的下一个选项感觉有点 self-defeating,因为它需要重新声明 Method
中的所有值,但是,您可以继续使用 axios
Method
类型,你肯定会有一个模式来解析 Method
中的所有值(即,不会屈服于上述问题):
import { z } from "zod";
import { Method } from "axios";
const METHOD_MAP: { [K in Method]: null } = {
get: null,
GET: null,
delete: null,
DELETE: null,
head: null,
HEAD: null,
options: null,
OPTIONS: null,
post: null,
POST: null,
put: null,
PUT: null,
patch: null,
PATCH: null,
purge: null,
PURGE: null,
link: null,
LINK: null,
unlink: null,
UNLINK: null
};
const METHODS = (Object.keys(METHOD_MAP) as unknown) as readonly [
Method,
...Method[]
];
const methods: z.ZodType<Method> = z.enum(METHODS);
METHODS
的类型断言在这里是安全的,因为 METHODS_MAP
没有导出,我们确切地知道它有什么键。现在,如果缺少任何 Method
值,METHOD_MAP
对象将导致类型错误,这意味着生成的模式将解析所有 Method
值作为编译时强制执行的保证。