Zod + Quasar报错:无法解析类型引用或不支持内置工具类型
解决Vue 3中Zod推断类型无法用于defineProps的问题
你遇到的Error: Unresolvable type reference or unsupported built-in utility type,核心原因是Vue的单文件组件编译器在处理defineProps的类型参数时,无法解析z.infer<ReturnType<typeof PropsSchema>>这种嵌套的返回值类型推断——它只能识别更直接、可静态分析的类型定义。
下面是几种可行的解决方案:
方案1:将Zod Schema改为非函数式定义
如果你的Schema不需要动态生成(比如不需要根据参数调整结构),直接把Schema定义为静态对象即可,这样Vue编译器能正常解析推断出的类型:
修改inputBase.ts
import { z } from 'zod'; // 移除包裹函数,直接定义Schema export const PropsBaseSchema = z.object({ placeholder: z.string().optional(), rules: z.array(z.any()).optional(), disable: z.boolean().optional(), readonly: z.boolean().optional(), }); export type PropsBase = z.infer<typeof PropsBaseSchema>;
修改largeDto.ts
import { z } from 'zod'; import { PropsBaseSchema } from './base/inputBase'; // 直接基于静态Schema扩展 export const PropsSchema = PropsBaseSchema.extend({ type: z.enum(['text', 'password', 'textarea', 'email', 'search', 'tel', 'url']).optional(), }); export type PropsDto = z.infer<typeof PropsSchema>;
组件代码保持不变
<script setup lang="ts"> import { PropsSchema } from './dto/largeDto'; import type { PropsDto } from './dto/largeDto'; const props = withDefaults(defineProps<PropsDto>(), { type: 'text', }); PropsSchema().parse(props); // 运行时验证正常工作 </script>
方案2:保留函数式Schema,优化类型推断
如果必须用函数式Schema(比如需要动态生成Schema结构),可以通过创建临时Schema实例来简化类型推断,让Vue编译器能识别:
修改largeDto.ts
import { z } from 'zod'; import { PropsBaseSchema } from './base/inputBase'; export const PropsSchema = () => PropsBaseSchema().extend({ type: z.enum(['text', 'password', 'textarea', 'email', 'search', 'tel', 'url']).optional(), }); // 创建临时实例,基于它推断类型,避免嵌套的ReturnType引用 const _tempSchema = PropsSchema(); export type PropsDto = z.infer<typeof _tempSchema>;
组件代码无需修改,即可正常使用defineProps<PropsDto>。
方案3:结合Vue props的运行时验证
如果你想同时利用Vue内置的props验证和Zod的强校验,可以把Zod Schema转换成Vue的props验证规则,同时保留类型推断:
<script setup lang="ts"> import { PropsSchema } from './dto/largeDto'; import type { PropsDto } from './dto/largeDto'; import { onMounted } from 'vue'; // 定义Vue props验证规则,复用Zod的校验逻辑 const props = withDefaults(defineProps<PropsDto>({ placeholder: String, rules: Array, disable: Boolean, readonly: Boolean, type: { type: String, validator: (value: string) => PropsSchema().shape.type.safeParse(value).success } }), { type: 'text' }); // 组件挂载时做全量Zod验证 onMounted(() => { PropsSchema().parse(props); }); </script>
内容的提问来源于stack exchange,提问作者Benson
相关产品推荐
相关产品推荐

