I’m using supabase. In supabase, API response is structured like {data, error}
. data
is non-null if the request is succeeded and error
is non-null if the request is failed.
So If I want to call an api, I have to handle the response like this:
const {data, error} = await getData();
if (error) {
throw error;
}
// data is non-null (succeeded)
It could be very burdened if the response is an array:
const [{data: d1, error: e1}, {data: d2, error:e2}] = await Promise.all([getData1(), getData2()]);
if (e1 || e2) {
throw e1 || e2;
}
// d1 and d2 are non-null
So I’ve created an util function to reduce the effort.
import {type PostgrestError} from "@supabase/supabase-js";
interface IResponse<T> {
data: T;
error: PostgrestError | null;
}
interface ISuccessResponse<T> extends IResponse<T> {
data: NonNullable<T>;
error: null;
}
const isDataResponse = <T>(res: IResponse<T>): res is ISuccessResponse<T> => !res.error;
export const throwIfError = <T>(res: IResponse<T>): ISuccessResponse<T> => {
if (isDataResponse(res)) {
return res;
}
throw res.error;
};
// very simple!
const {data} = throwIfError(await getData());
// data is non-null!
It works well if the response is not an array. However it cannot handle array response.
const [{data: d1}, {data: d2}] = throwIfError(await Promise.all([getData1(), getData2()]));
I surely know how to write a logic for JS but not TS.
export const throwIfError = res => {
if (Array.isArray(res)) {
if (res.every(isDataResponse)) {
return res;
}
throw res.find(r => !isDataResponse(r)).error;
}
if (isDataResponse(res)) {
return res;
}
throw res.error;
}
I want throwIfError
to handle array response as well. Could you help me?