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

使用Supabase认证结合React Toolkit Query时queryFn出现TypeScript类型错误

使用Supabase认证结合React Toolkit Query时queryFn出现TypeScript类型错误

看起来你遇到的核心问题是TypeScript类型不匹配,具体来说是自定义的响应类型和RTK Query要求的返回结构、Supabase实际返回的数据结构三者没对齐。我来一步步帮你拆解和解决:

错误根源分析

从报错信息能看出来几个关键点:

  1. 你定义的SignupResponse接口和SupabasesignUp返回的data(包含user和session字段)完全没有交集,导致返回{ data }时类型冲突。
  2. RTK Query的queryFn要求返回的QueryReturnValue结构中,data必须严格匹配你在mutation泛型里定义的类型,而你当前的返回值结构不符合这个要求。
  3. 你尝试用AuthResponse时也踩了坑:Supabase的AuthResponse是包含data和error的整体结构,但RTK Query的mutation泛型第一个参数是成功时的data类型,不是整个响应对象,所以直接用会导致类型不兼容。

解决方案步骤

1. 修正类型定义,对齐Supabase返回结构

首先我们要明确成功和错误场景的类型,让它们既符合Supabase的返回格式,又满足RTK Query的要求:

// 先导入Supabase的内置类型,确保类型引用正确
import { User, Session, AuthError } from '@supabase/supabase-js';

// 定义成功响应的类型,完全对齐Supabase signUp返回的data结构
type SignupSuccessData = {
  user: User | null;
  session: Session | null;
};

// 定义错误响应的类型,包含错误信息和状态码
type SignupError = {
  message: string;
  status: number;
};

// 顺便修正你的Signup类型(之前写错了Schema名称)
const SignupForm = z.object({
  email: z.string().email({ message: "Please enter a valid email address." }),
  password: z
    .string()
    .min(6, { message: "Minimum 6 characters." }) // 你之前写的是2,这里应该是6?
    .max(50, { message: "Maximum 50 characters." }),
  confirmPassword: z.string().min(6).max(50),
  name: z.string().min(2, { message: "Name must be at least 2 characters." }),
});
type Signup = z.infer<typeof SignupForm>; // 这里应该是SignupForm,不是SignupApi

2. 调整queryFn的返回逻辑,匹配RTK Query要求

RTK Query的queryFn返回值只能是两种结构:{ data: 成功类型 } 或者 { error: 错误类型 },我们要确保所有分支都严格符合这个规则:

signupWithCredentials: builder.mutation<SignupSuccessData, Signup>({
  async queryFn({ email, password }) {
    const { data, error } = await supabase.auth.signUp({
      email,
      password,
    });

    // 处理邮箱已存在的特殊场景(Supabase返回的user.identities为空)
    if (data?.user?.identities?.length === 0) {
      return {
        error: {
          message: "Email already registered",
          status: 409, // 用409(冲突)比500(服务器错误)更符合HTTP语义
        } as SignupError,
      };
    }

    // 处理Supabase返回的其他错误
    if (error) {
      return {
        error: {
          message: error.message,
          status: error.status ?? 500, // 给个默认值,避免status为undefined
        } as SignupError,
      };
    }

    // 兜底处理:如果没有error但data为空的异常情况
    if (!data) {
      return {
        error: {
          message: "Unexpected error occurred",
          status: 500,
        } as SignupError,
      };
    }

    // 成功场景:返回符合SignupSuccessData类型的data
    return { data };
  },
}),

额外提示

  • 状态码尽量使用符合HTTP语义的数值,比如邮箱重复用409,参数错误用400,服务器错误用500,这样前端处理错误时更清晰。
  • 如果不想自己定义类型,可以直接复用Supabase的AuthResponse['data']作为成功类型,这样更省心:type SignupSuccessData = AuthResponse['data'];

备注:内容来源于stack exchange,提问作者Pratik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 11:17:57