从构造函数选项推断类型

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

这可行,但我确信有更好的方法可以做到这一点,我使用 zod 对用户零控制的值进行模式验证。

const SchemaValue = z.object({
  translatedValue: z.string().or(z.number())
});

const SchemaInput = z.object({
  truncate: z.number()
});

然后我有一个非常简单的类,它采用这些模式并执行验证,并将类型推断回传递给“操作”的方法。

interface ActionOptions<I, V> {
  name: string;
  inputSchema: z.AnyZodObject;
  valueSchema: z.AnyZodObject;
  validator: (input: I, value: V) => Promise<[string | null, boolean]>;
}

export class Action<I, V> {
  options: ActionOptions<I, V>;
  constructor(options: ActionOptions<I, V>) {
    this.options = options;
  }

  async run(value: V, input: I): Promise<void> {
    // additional code is here to validate value & input against valueSchema and inputSchema
    await this.options.validator(
      input,
      value,
    );
  }
}

然后我像这样使用它:

const action = new Action<z.infer<typeof InputSchema>, z.infer<typeof ValueSchema>>({
  inputSchema: InputSchema,
  valueSchema: ValueSchema,
  name: 'someAction',
  async validator(input, value) {
    return [null, true];
  }
});

这是可行的,验证器上输入和值的智能感知是正确的,但是我忍不住认为有一种更好的方法可以实现这一点,而不必将类型传递给构造函数,我问的唯一原因是我我正在努力使

Action
的使用尽可能简单!

我想知道是否有一种方法可以从 inputSchema 和 valueSchema 推断类型,而无需在调用新实例时通过构造函数传递它们?

typescript class types type-inference zod
1个回答
2
投票

问题

z.AnyZodObject
不是通用的,会删除任何自动推理。

解决方案

使用

z.Schema<T>
自动推断类型,因为它是泛型。

示例

...
interface ActionOptions<I, V> {
  name: string;
  inputSchema: z.Schema<I>;
  valueSchema: z.Schema<V>;
  validator: (input: I, value: V) => Promise<[string | null, boolean]>;
}
...

const action = new Action({
  inputSchema: InputSchema,
  valueSchema: ValueSchema,
  name: 'someAction',
  async validator(input, value) {
    return [null, true];
  }
});

编辑和警告

只要您不使用

zod
的更高级功能(例如
.optional().default(1)
),上述解决方案就有效。如果您是,这里有一个适用于上述操作和变革操作的替代方案。

const OptionalValue = z.object({
  translatedValue: z.number().optional().default(1),
});

function validateIncorrect<T>(schema: z.Schema<T>, value: unknown, callback: (validatedValue: T) => void) {
  const validatedValue = schema.parse(value);
  return callback(validatedValue);
}

validateIncorrect(OptionalValue, { translatedValue: 2 }, (v) => {
  // incorrect
  // { translatedValue?: number | undefined; }
  console.log(v); 
});

function validateCorrect<T extends z.AnyZodObject>(schema: T, value: unknown, callback: (validatedValue: z.infer<T>) => void) {
  const validatedValue = schema.parse(value);
  return callback(validatedValue);
}
validateCorrect(OptionalValue, { translatedValue: 2 }, (v) => {
  // correct
  // { translatedValue: number; }
  console.log(v);
});
© www.soinside.com 2019 - 2024. All rights reserved.