kiliman / remix-typedjson

This package is a replacement for superjson to use in your Remix app. It handles a subset of types that `superjson` supports, but is faster and smaller.
MIT License
444 stars 22 forks source link

How to deserialize fetch response from non-Remix API #41

Open wave-light opened 4 months ago

wave-light commented 4 months ago

Is it possible to use this library to deserialize a fetch response from an API endpoint that is not a Remix loader or action? In other words, to use this library on a Response object, to deserialize the typedjson Response that was retuned?

kiliman commented 4 months ago

Yes, you don't need Remix to use it.

// api.ts
import { serialize } from `remix-typedjson`

return Response.json(serialize(payload))

// client.ts
import { deserialize } from `remix-typedjson`

const response = await fetch('/api')
const json = await response.json()
const payload = deserialize<PayloadType>(json)
wave-light commented 4 months ago

@kiliman thanks for you reply. This works, but I am getting a type error when passing json to deserialize:

Argument of type 'unknown' is not assignable to parameter of type 'TypedJsonResult'.

If I then add generic type argument to response.json, eg res.json<{foo: string}>(), I get the following type error:

Type '{ foo: string; }' has no properties in common with type 'TypedJsonResult'.
kiliman commented 4 months ago

Try:

import { deserialize, type TypedJsonResult } from 'remix-typedjson'

const json = await response.json() as TypedJsonResult
const payload = deserialize<PayloadType>(json)
wave-light commented 4 months ago

@kiliman Thanks, that works.

By the way, if using this approach with a remix loader to return the payload (say you are using fetch to fetch the loader), then the payload object type is not being infered with typeof loader, eg:

export async function loader({ request }: LoaderFunctionArgs) {
  return serialize({ foo: 'bar' });
}

type MyLoader = ({ request }: LoaderFunctionArgs) => Promise<TypedJsonResult>

here, MyLoader type is inferred as type MyLoader = ({ request }: LoaderFunctionArgs) => Promise<TypedJsonResult>.

However, if you use typedjson to serialize the response, the payload stucture can be inferred correctly.