我正在创建一个名为
createDefinition
的函数,它以 Zod 对象作为参数,使用 ZodType
来缩小可以传递给它的允许的 Zod 形状(在本例中,仅使用 JSON)。
但是,因为这个函数always需要一个
z.object()
并且会被调用很多次,所以最好只将传递对象的内部属性作为参数,以避免每次都键入z.object()
想要调用 createDefinition
— 为了方便起见,它将在其内部调用 z.object({ ...passedProps })
。
我正在努力以创建类型兼容的 Zod 对象的方式键入我的函数输入(请参阅下面的版本 2)。
z.object()
传递给它):type Result<S extends JsonObject> = {
_schema: ZodType<S>;
};
export const createDefinition = <Shape extends JsonObject>(
schema: z.ZodType<Shape>,
): Result<Shape> => {
// ... Do stuff
return {
_schema: schema,
};
};
createDefinition(z.object({
string: z.string(),
date: z.date(), // TypeError -> as expected
}));
type Result<S extends JsonObject> = {
_schema: ZodType<S>;
};
export const createDefinition = <Shape extends JsonObject>(
schemaProperties: {
[K in keyof Shape]: z.ZodType<Shape[K]>,
}
): Result<Shape> => {
const schema = z.object(schemaProperties);
// ... Do stuff
return {
_schema: schema, // Type error :: `schema` doesn't match ZodType<Shape>
};
};
createDefinition({
string: z.string(),
date: z.date(), // No TypeError?
});
z.object
接受 ZodRawShape
,它是具有 ZodTypeAny
值的对象。我们需要将这些值限制为 Zod 类型以获得有效的 JSON 值类型。
这里有一种方法,通过定义 JSON 值的类型并将其传递给
ZodRawShape
来定义新的更窄的 ZodType
等价物。然后我们可以使用新的形状类型作为我们的通用参数类型。
import { z, ZodType } from 'zod';
type JsonValue = string | number | boolean | Array<JsonValue> | JsonObject;
type JsonObject = { [x: string]: JsonValue };
type ZodRawJsonShape = Record<string, ZodType<JsonValue>>;
function createDefinition<T extends ZodRawJsonShape>(schema: T) {
return z.object(schema);
};
const valid = createDefinition({
a: z.string(),
b: z.number(),
c: z.array(z.string()),
d: z.object({ foo: z.array(z.string()) })
})
const invalid = createDefinition({
a: z.string(),
b: z.object({
foo: z.string(),
}),
c: z.date(), // Error
d: z.array(z.date()) // Error
e: z.object({ // Error
bar: z.date()
})
});