Supabase查询中条件类型引发TypeScript 'never'类型赋值错误
问题根源:
DbResultOk 类型定义与使用不匹配 问题原因分析
你定义的DbResultOk<T>类型逻辑是仅当传入的T是包含data字段的PromiseLike类型时,才提取data的类型并排除null值;如果传入的T不是PromiseLike类型,条件判断不成立,类型就会回退为never。
现在你在代码中直接传入了Tables<"FuenteIngreso">[](这是一个数组类型,而非Promise),导致T extends PromiseLike<{ data: infer U }>的条件不满足,DbResultOk<T>最终解析为never,自然触发了类型不匹配的报错。
同时你的辅助类型设计存在逻辑偏差:DbResultOk的初衷应该是从Supabase查询的Promise结果中提取成功的data类型,但当前定义要求输入必须是Promise,你却直接传入了最终的data类型(数组),完全偏离了类型的设计意图。
修正方案
方案1:调整DbResultOk定义,支持多场景使用
修改类型定义,让它既能处理Promise类型,也能直接处理数据/结果对象类型:
// 通用逻辑:提取data字段并排除null type ExtractNonNullData<T> = T extends { data: infer U } ? Exclude<U, null> : Exclude<T, null>; // 处理Promise或直接传入的类型 export type DbResultOk<T> = T extends PromiseLike<infer U> ? ExtractNonNullData<U> : ExtractNonNullData<T>;
方案2:按原设计正确使用DbResultOk
如果不想修改类型定义,应该传入查询的Promise类型(typeof query)来获取正确的data类型,而非直接传入数组:
export async function addFrequentIngresoAccion(payload: { // ... payload definition }): Promise<DbResult<any>> { const supabase = createServerActionClient<Database>({ cookies }); const query = supabase.from("FuenteIngreso").insert([/*...*/]).select(); const result: DbResult<typeof query> = await query; if (result.error) { const resultErr: DbResultErr = result.error; return { error: resultErr }; } // 正确传入Promise类型获取data类型 type FuenteIngresoData = DbResultOk<typeof query>; const resultOk: FuenteIngresoData = result.data as FuenteIngresoData; return { data: resultOk }; }
优化函数返回类型
另外,函数返回类型Promise<DbResult<any>>过于宽泛,建议明确返回类型以获得更好的类型提示:
// 定义明确的返回类型 type AddFrequentIngresoResult = | { data: DbResultOk<typeof query> } | { error: DbResultErr }; export async function addFrequentIngresoAccion(payload: { // ... payload definition }): Promise<AddFrequentIngresoResult> { const supabase = createServerActionClient<Database>({ cookies }); const query = supabase.from("FuenteIngreso").insert([/*...*/]).select(); const result = await query; if (result.error) { return { error: result.error }; } const resultOk = result.data as DbResultOk<typeof query>; return { data: resultOk }; }
额外提示
DbResult<T>的定义是合理的,但应避免在返回类型中使用DbResult<any>,否则会失去TypeScript的类型校验意义。- Supabase自动生成的
Database类型已经包含了查询返回的精确类型,你可以直接基于它来定义类型,无需完全自定义辅助类型。
内容的提问来源于stack exchange,提问作者Vladimirzb
相关产品推荐
相关产品推荐

