Как преобразовать рекурсивную общую форму (машинописный текст)

Мне нравится синтаксический анализатор 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>>ближе к тому, что вам действительно нужно.

Другие вопросы по тегам