Как преобразовать рекурсивную общую форму (машинописный текст)
Мне нравится синтаксический анализатор Zod, но, возможно, я надул голову, создав библиотеку форм.
В идеальном конечном состоянии входная форма трансформируется для создания
{ fieldA: { value, onChange, errors } }
. Он работает на одном уровне, но неясно, как поддерживать массивы и вложенные объекты.
Может ли машинописный текст преобразовать рекурсивные дженерики таким образом?
Zod представляет такие парсеры:
const schema = z
.object({
name: z.string().min(3, 'Too short.'),
nested: z.object({
name: z.string(),
}),
repeat: z.array(z.object({
arrNest: z.string(),
})),
}).transform((v) => v.name);
Затем, используя вывод типа:
const example = <Input extends { [v: string]: any }, Output extends unknown>(
schema: z.ZodType<Output, any, Input>
) => {
type Fields = {
[P in keyof Input]: {
value: Input[P];
};
};
return ({} as unknown) as Fields;
};
export const typed = example(schema);
Имя имеет желаемый тип
{ value: string }
но повторить:
Вместо этого я хочу применить это рекурсивно с объектами и массивами
потом
types.repeat
имел бы тип
{ arrNest: { value: string } }[]
Примечания
Тип объекта зод довольно сложный ..
но меня беспокоит только
Input
, представленный как
export type ZodRawShape = { [k: string]: ZodTypeAny };
Любые мысли по поводу осуществимости или направления приветствуются!
1 ответ
Я не уверен на 100%, что правильно понял вашу потребность, но условные операторы типа + infer должны получить то, что вы хотите. Что-то вроде этого:
function example<Input extends { [v: string]: any }>(i: Input) {
type Fields<I> = {
[P in keyof I]: I[P] extends object
? Fields<I[P]>
: I extends Array<infer A>
? Fields<A>[]
: { value: I[P] }
};
return i as Fields<Input>;
}
type Input = {
toto: number;
nested: { tutu: string };
array: { stuff: boolean }[];
};
const typed = example({} as Input);
typed.array[0].stuff.value = true;
typed.toto.value = 13;
typed.nested.tutu.value = 'dojz';
Я использовал необработанный объект в качестве входных данных, поэтому вам нужно адаптировать его к Zod, но это не должно быть слишком сложно, если вы знаете структуру объектов Zod. Возможно, используя
Fields<zod.infer<typeof schema>>
ближе к тому, что вам действительно нужно.