使用 Zod 模式实现工厂模式时存在类型推断问题

问题描述 投票:0回答:1

当架构在父函数中定义时,如何根据指定的函数参数推断类型?我正在尝试实现工厂模式,但遇到类型推断问题。这是我想要实现的目标的示例:

import { z } from 'zod';

export const makeClient = <T extends string>({
  schemas,
}: {
  schemas: {
    [key in T]: z.ZodSchema;
  };
}) => {
  type Keys = keyof typeof schemas;
  type Values<K extends Keys> = z.infer<typeof schemas[K]>;

  return {
    async findOne<K extends Keys>({
      name,
      filter,
    }: {
      name: K;
      filter: Values<K>;
    }) {
      return { name, filter };
    },
  };
};

const client = makeClient({
  schemas: {
    test: z.object({
      value: z.number(),
    }),
  },
});

client.findOne({
  name: "test", // this is inferred
  filter: {
    // not inferred
  }
})

我相信在这种情况下应该可以实现类型推断,但我很难弄清楚如何实现。任何指导将不胜感激。

javascript typescript zod
1个回答
0
投票

我整理了一个由架构映射驱动的客户端草图,该架构映射从架构映射中推断键以驱动函数参数中的智能感知,并从架构结构推断返回类型。

我无法轻松地与原始实现保持一致,因为 findOne 似乎没有执行任何操作,因此没有任何与运行时模式的实际绑定。相比之下,下面的示例对检索到的数据进行运行时检查(使用运行时模式),然后从中推断出类型。

import { z, type ZodSchema} from 'zod';
import axios from 'axios'

type RecordKey<R> = R extends Record<infer K, unknown> ? K : never

export const makeClient = <const R extends Record<string, ZodSchema<unknown>>>(schemas:R) => {
  return {
    async retrieve<K extends RecordKey<R>>(key: K, id:string): Promise<z.infer<R[K]>>{
      const value = await axios.get(`/item/${key}/${id}`)
      return schemas[key].parse(value.data)
    }
  };
};

const client = makeClient(
  {
    accumulator: z.object({
      count: z.number(),
    }),
  } as const);


const retrieved = await client.retrieve("accumulator", "48092234")

您可以对其进行实验,并在 https://tsplay.dev/WoebgN

查看密钥和返回类型推断
© www.soinside.com 2019 - 2024. All rights reserved.