Closed Lilja closed 9 months ago
I think I solved it:
type SuperJsonOutput = {tag: "Ok" | "Err", payload: string};
export const superJsonRegister = (
_superjson: typeof superjson,
): Parameters<
typeof superjson.registerCustom<Result<unknown, unknown>, SuperJsonOutput>
>[0] => {
return {
isApplicable: (value): value is Result<unknown, unknown> =>
Result.isResult(value),
serialize: (value: Result<unknown, unknown>) => {
if (value.isOk()) {
return {tag: "Ok", payload: _superjson.stringify(value.value)};
}
return {tag: "Err", payload: _superjson.stringify(value.error)};
},
deserialize: (value: SuperJsonOutput) => {
if (value.tag === "Ok") {
return Ok(_superjson.parse(value.payload));
} else {
return Err(_superjson.parse(value.payload));
}
},
};
Which works with
test("number", () => {
superjson.registerCustom(superJsonRegister(superjson), "Result");
const result = Result.Ok<number, Error>(1);
const serialized = superjson.serialize(result);
const deserialized = superjson.deserialize<Result<number, Error>>(serialized);
if (deserialized.isOk()) {
expect(deserialized.value).toEqual(result.value);
}
else {
throw new Error("deserialized is not ok");
}
});
I have a
Result
utility, that helps me write result-based interfaces, like how rust does it. I'm using tRPC between the client and server, and I would like to re-use my utility over the wire.It looks sort of like this:
Running SuperJSON as is works great, except for that the functions are not persisted over wire. Which is totally expected. You would need some sort of custom recipe.
The problem which I don't fully understand is how I would use
registerCustom
if my data is sayResult<number, Error>
.But since I
JSON.stringify
, it messes up thenumber
. In this case I would expect another parameter that I could "continue" the serialization:My test, where I use
Result<number, Error>
.Any thoughts on this?