You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript判别联合类型结合Zod解析报错求助

TypeScript判别联合类型与Zod safeParse返回值类型问题

我尝试用TypeScript实现判别联合类型,在条件分支处理时遇到问题。当前代码如下:

import { z, ZodError } from 'zod';

let parsedUser = z.object({
    password: z.string().min(1).max(8),
    firstName: z.string().min(1).max(8),
    lastName: z.string().min(1).max(8)
});

type User = {
    password: string,
    firstName: string,
    lastName: string
}

type UserParserOutcome =
    ZodError | User;

export const userParser = (user: unknown): UserParserOutcome => {
    let result = parsedUser.safeParse(user);

    if (!result.success)
        return result.error;
    else
        return result.data as User;
};

问题:我定义了UserParserOutcome作为ZodError或User的联合类型,按Zod文档,safeParse应返回error或data属性。else分支正常,但WebStorm标记return result.error行报错,请问遗漏了什么?


问题原因

Zod的safeParse返回的error并非通用的ZodError类型,而是带泛型参数的ZodError<z.infer<typeof parsedUser>>——也就是和当前schema绑定的具体错误类型。TypeScript会严格区分泛型类型和基础类型,所以直接返回result.error时,类型无法匹配你手动定义的UserParserOutcome中的ZodError。

另外,你手动定义的User类型其实和parsedUser schema的类型重复了,完全可以用Zod的类型推导来避免重复维护。

解决方案

有两种可行的修改方式:

方案1:让TypeScript自动推导返回类型

去掉手动定义的UserParserOutcome,直接让TS根据safeParse的结果自动推导函数返回类型,同时用z.infer推导User类型:

import { z, ZodError } from 'zod';

const parsedUser = z.object({
    password: z.string().min(1).max(8),
    firstName: z.string().min(1).max(8),
    lastName: z.string().min(1).max(8)
});

// 自动推导User类型
type User = z.infer<typeof parsedUser>;

// 去掉手动定义的返回类型,让TS自动推导
export const userParser = (user: unknown) => {
    const result = parsedUser.safeParse(user);
    if (!result.success) return result.error;
    return result.data;
};

方案2:修正手动定义的联合类型

如果一定要保留UserParserOutcome,需要将其中的ZodError替换为和schema绑定的具体错误类型,同时用z.infer推导User:

import { z, ZodError } from 'zod';

const parsedUser = z.object({
    password: z.string().min(1).max(8),
    firstName: z.string().min(1).max(8),
    lastName: z.string().min(1).max(8)
});

type User = z.infer<typeof parsedUser>;
// 绑定schema的具体ZodError类型
type UserParserOutcome = ZodError<User> | User;

export const userParser = (user: unknown): UserParserOutcome => {
    const result = parsedUser.safeParse(user);
    if (!result.success) return result.error;
    return result.data;
};

额外说明

  • 把let parsedUser改成const parsedUser,这样TypeScript能更精准地推导schema的类型。
  • 不需要用as User断言result.data,因为safeParse成功时data的类型已经是User了,断言完全多余。

内容的提问来源于stack exchange,提问作者user1790300

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:06:42