javascript - 如何重写函数中的接口(interface)并保持正确的返回类型?

标签 javascript typescript vite zod

我有一个definePlugin函数,它接受一个实现PluginConfig接口(interface)的对象,并带有默认的RequestValidator。我正在尝试重写此接口(interface),提供自定义验证器,同时确保返回值具有正确的类型。但是,我当前的实现导致返回的 vueAuth 类型为 any。如何在保持正确的返回类型的同时重写接口(interface)? 这是我当前的代码:

import { z } from 'zod'

// Create de default validator
export const EmailValidator = z.object({
  email: z
    .string({ required_error: 'auth.validation.email' })
    .email({ message: 'auth.validation.email_format' })
})

// The default interface the generic should at least implement
interface PluginConfig {
  validator?: z.ZodType
}

// The default interface with the default validator to use if not overriden
interface DefaultPluginConfig {
  validator?: typeof EmailValidator
}

const definePlugin = <T extends PluginConfig = DefaultPluginConfig>({
  validator = EmailValidator
}: T) => {
  return validator.parse({})
}

const test = definePlugin({})
// Object should look like EmailValidator but is any instead
test.email

// Create a custom validator
const CustomValidator = z.object({
  email: z.string(),
  username: z.string()
})

// Create a custom interface to use as generic
interface CustomConfig {
  validator?: typeof CustomValidator
}

const test2 = definePlugin<CustomConfig>({
  validator: CustomValidator
})
// Object should look like CustomValidator but is any instead
test2.username
test2.username

在提供自定义验证器时,我应该进行哪些更改以确保 DefinePlugin 具有正确的类型?

最佳答案

您的代码中存在一些导致问题的问题:

  1. 您已将 PluginConfig 定义为属性 z.ZodType,它是类型而不是值。您可以修改为:

    接口(interface)插件配置{ 验证器?:z.Schema; }

  2. 在您的代码中,您的 DefaultPluginConfig 接口(interface)未正确扩展 PluginConfig。您可以将其更改为:

    接口(interface) DefaultPluginConfig 扩展了 PluginConfig { 验证器?:EmailValidator 类型; }

您的代码如下所示:

import { z } from 'zod';

// Create the default validator
export const EmailValidator = z.object({
  email: z
    .string({ required_error: 'auth.validation.email' })
    .email({ message: 'auth.validation.email_format' }),
});

// The default interface the generic should at least implement
interface PluginConfig {
  validator?: z.Schema<any>;
}

// The default interface with the default validator to use if not overridden
interface DefaultPluginConfig extends PluginConfig {
  validator?: typeof EmailValidator;
}

const definePlugin = <T extends PluginConfig = DefaultPluginConfig>({
  validator = EmailValidator,
}: T) => {
  return validator.parse({});
};

const test = definePlugin({});
test.email; // Object has the correct type EmailValidator

// Create a custom validator
const CustomValidator = z.object({
  email: z.string(),
  username: z.string(),
});

// Create a custom interface to use as generic
interface CustomConfig extends PluginConfig {
  validator?: typeof CustomValidator;
}

const test2 = definePlugin<CustomConfig>({
  validator: CustomValidator,
});
test2.username; // Object has the correct type CustomValidator
test2.email; // Object has the correct type CustomValidator (from CustomValidator)

如果您仍然遇到任何问题,请告诉我。

更新代码(最终):

根据聊天讨论,正确答案是:

import { z, ZodType } from "zod";

// Create the default validator
export const EmailValidator = z.object({
  email: z.string().default("")
});

// The default interface the generic should at least implement
interface PluginConfig<T extends ZodType = typeof EmailValidator> {
  validator?: T;
}

const definePlugin = <
  T extends PluginConfig = PluginConfig<typeof EmailValidator>,
  R = T extends PluginConfig<infer V> ? V : ZodType
>({
  validator = EmailValidator
}: T): R extends ZodType<infer P> ? P : never => {
  return validator.parse({}) as any;
};

const test = definePlugin({});
test.email; // Object has the correct type EmailValidator

const CustomValidator = z.object({
  email: z.string().default(""),
  username: z.string().default("")
});

type CustomConfig = PluginConfig<typeof CustomValidator>;

const test2 = definePlugin<CustomConfig>({
  validator: CustomValidator
});

console.log(test2.username);

所以这里Generic V和P分别用于从PluginConfigZodType捕获类型。

这里,
V - 表示 PluginConfig 中验证器属性的推断类型
P - 表示 ZodType 的推断类型

这些泛型 VP 允许函数处理不同的验证器配置并基于它返回合适的推断类型。

关于javascript - 如何重写函数中的接口(interface)并保持正确的返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76430738/

相关文章:

javascript - 验证仅在所有文本输入均为空白时有效,而不是任何文本输入为空白

javascript - 使用 Canvas 或 SVG 在整个页面上放置一个蒙版

html - 如何从 Angular 6 中的另一个组件的 typescript 激活和停用组件中的样式?

javascript - 从对象数组创建 PrimeNG TreeTable json

debugging - 如何在 lan --host 上调试 Vue 3 Vite

javascript - React-router-dom v6 仅渲染默认路由

javascript - Cordova Android 应用程序上的 Ajax 请求失败

javascript - jQuery 以编程方式选择值 - 奇怪的问题

typescript - 通过 TypeScript API 或 ts-morph 从模块中获取所有可能的导出

javascript - 使用 Vue 插件的 Vite MPA 是如何工作的?