H
Hono3mo ago
Josh

Does anyone have any recommendations for handling RPC response errors?

I want to do something like the parseResult function below so I can have consistent error handling across my app, but I've been struggling with getting type generics to work on the parseResult function such that the result type is correct. I'm kind of curious if anyone has recommendations on how to best handle using the rpc client throughout the app, or maybe I'm just over complicating things.
export async function fetchCentering(id: number) {
const client = getClient();

const result = await client.api.app.centering[':id'].$get({
param: { id }
});

const parsed = await parseResult(result);

return parsed;
}

async function parseResult(result) {
if (!result.ok) {
const errorData = await result.text();
throw new Error(errorData || 'Failed');
}

return await result.json();
}
export async function fetchCentering(id: number) {
const client = getClient();

const result = await client.api.app.centering[':id'].$get({
param: { id }
});

const parsed = await parseResult(result);

return parsed;
}

async function parseResult(result) {
if (!result.ok) {
const errorData = await result.text();
throw new Error(errorData || 'Failed');
}

return await result.json();
}
3 Replies
ambergristle
ambergristle3mo ago
what issue are you running into with the type generics? the solution hinges a bit on how you want to use the resulting data, but something like this should work pretty well
const parseResponse = async (response: Response) => {
if (!result.ok) {
return {
ok: false,
message: await response.text(),
}
}

return {
ok: true,
data: await response.json(),
}
}
const parseResponse = async (response: Response) => {
if (!result.ok) {
return {
ok: false,
message: await response.text(),
}
}

return {
ok: true,
data: await response.json(),
}
}
Josh
JoshOP3mo ago
So in your example you still need some type of type generic so that the result doesnt come back as any or unknown. I havent been able to get the result data to be typed properly from the rpc client. Oh, I think I got it! I did some more research on how to add types to just a regular fetch, and found an example where they made a new type generic for the json/text functions themselves.
interface ResponseSuccess<T> extends Response {
ok: true;
json(): Promise<T>;
text(): Promise<string>;
}

interface ResponseFailure extends Response {
ok: false;
json(): Promise<{ message: string }>;
text(): Promise<string>;
}

type ParsedResponse<T> = ResponseSuccess<T> | ResponseFailure;

async function parseResponse<T>(response: ParsedResponse<T>): Promise<T> {
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to fetch centering');
}

return await response.json();
}
interface ResponseSuccess<T> extends Response {
ok: true;
json(): Promise<T>;
text(): Promise<string>;
}

interface ResponseFailure extends Response {
ok: false;
json(): Promise<{ message: string }>;
text(): Promise<string>;
}

type ParsedResponse<T> = ResponseSuccess<T> | ResponseFailure;

async function parseResponse<T>(response: ParsedResponse<T>): Promise<T> {
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to fetch centering');
}

return await response.json();
}
ambergristle
ambergristle3mo ago
nice! seems legit

Did you find this page helpful?