I'm trying to send better-result types from the backend into our frontend via TRPC, and writing the serializer is not as trivial as I would hope.
The isSerializedResult does not feel specific enough for me:
function isSerializedResult(obj: unknown): obj is SerializedResult<unknown, unknown> {
return (
obj !== null &&
typeof obj === "object" &&
"status" in obj &&
((obj.status === "ok" && "value" in obj) || (obj.status === "error" && "error" in obj))
);
}
Sending status: 'ok' over our non-better-result API routes seems like it could easily happen, and we would then have a false positive deserialization.
Here's what my TRPC transformer looks like for now, only transforming from backend to frontend:
import { Err, Ok, Result } from 'better-result';
const trpcTransformer = {
input: {
deserialize: (obj: unknown): unknown => obj,
serialize: (obj: unknown): unknown => obj,
},
output: {
deserialize: (obj: unknown): unknown => {
// Result.serialize outputs { status: 'ok'|'error', value/error: ... }
if (
typeof obj === 'object' &&
obj !== null &&
'status' in obj &&
((obj as { status: string }).status === 'ok' ||
(obj as { status: string }).status === 'error')
) {
return Result.deserialize(obj);
}
return obj;
},
serialize: (obj: unknown): unknown => {
if (obj instanceof Ok || obj instanceof Err) {
return Result.serialize(obj as Result<unknown, unknown>);
}
return obj;
},
},
};
I'd like to have something close to this:
import { Err, Ok, Result } from 'better-result';
const trpcTransformer = {
input: {
deserialize: (obj: unknown): unknown => obj,
serialize: (obj: unknown): unknown => obj,
},
output: {
deserialize: (obj: unknown): unknown => {
if (isSerializedResult(obj)) {
return Result.deserialize(obj);
}
return obj;
},
serialize: (obj: unknown): unknown => {
if (isResult(obj)) {
return Result.serialize(obj as Result<unknown, unknown>);
}
return obj;
},
},
};
This leads to 2 ideas:
- Expose isSerializedResult and assertIsResult (or similar)
- Potentially make these checks more robust, with a more unique pattern than
'status' in value?
- The simpler solution here is to convert the entire codebase to only send Result types from the backend, but that's not always an option
Maybe there's another alternative to get this right that I can't think of though!
Great library 👌
I'm trying to send better-result types from the backend into our frontend via TRPC, and writing the serializer is not as trivial as I would hope.
The
isSerializedResultdoes not feel specific enough for me:Sending
status: 'ok'over our non-better-result API routes seems like it could easily happen, and we would then have a false positive deserialization.Here's what my TRPC transformer looks like for now, only transforming from backend to frontend:
I'd like to have something close to this:
This leads to 2 ideas:
'status' in value?Maybe there's another alternative to get this right that I can't think of though!
Great library 👌