flightcontrolhq / superjson

Safely serialize JavaScript expressions to a superset of JSON, which includes Dates, BigInts, and more.
https://www.flightcontrol.dev?ref=superjson
MIT License
4.13k stars 91 forks source link

How to keep TS types after serialization ? (getStaticProps) #224

Closed MatteoGauthier closed 1 year ago

MatteoGauthier commented 1 year ago

Hey ! I have an object that I want to serialize, and this object contains Date properties. I wanted to know if it's possible to keep the input types after the serialization ?

const project = {
    name: "hello",
    quantity: 12
    date: new Date()
}

const serialized = superjson.serialize(project)

console.log(serialized.name) // string
console.log(serialized.quanity) // number
console.log(serialized.date) // string
cjsewell commented 1 year ago

Not really in the serialized stage, as at that point its plain JSON with meta data. It needs to be deserialized to get the original types back.

Once you deserialize your data, then the types can be restored:

const project = {
    name: "hello",
    quantity: 12,
    date: new Date()
}

const serialized = superjson.serialize(project);
console.log(serialized.json.name);     // string
console.log(serialized.json.quantity); // string
console.log(serialized.json.date);     // string
console.log(serialized.meta);          // { values: { date: [ 'Date' ] } }

const deserialized = superjson.deserialize<typeof project>(serialized);
console.log(deserialized.name);     // string
console.log(deserialized.quantity); // number
console.log(deserialized.date);     // date
Skn0tt commented 1 year ago

Hi @MatteoGauthier, could you expand on your usecase? Why are you looking for serialized to have the same types as project?

MatteoGauthier commented 1 year ago

Hey ! I'm trying to use the getStaticProps of Next.js with data from Prisma. But in the data returned by Prisma I have some Date properties and I want to pass it to my Next page. How can I achieve that ?

export const getStaticProps = async (
  context: GetStaticPropsContext<{ id: string }>
) => {
  const { id } = context.params!;

  const project = await prisma.project.findUnique({
    where: {
      id,
    },
  });

  return {
    props: {
      project: serialize(project).json as unknown as Project,
      id,
    },
    revalidate: 60,
  };
};

Maybe a tricky Generic Type can convert every Date type to string type after the serialize function call.

Sorry for my hesitant explanations 😅

Skn0tt commented 1 year ago

Got it! Have you looked at https://github.com/blitz-js/babel-plugin-superjson-next? That should do all of that for you out of the box :)

shirshendubhowmick commented 1 year ago

@Skn0tt I tried the SWC plugin with pages directory. I noticed that it does the auto serialisation. However inside the component it doesn't auto deserialise.

Since you mentioned only about the babel plugin in your previous comment, does it mean auto deserialisation not available in the SWC plugin ? (In project readme it says it does)

Skn0tt commented 1 year ago

That sounds like a bug with https://github.com/blitz-js/next-superjson-plugin - could you please open a bug report over there?

Skn0tt commented 1 year ago

Closing this issue for now - @MatteoGauthier feel free to reopen if needed.