Tips for successfully transferring a JsonifyObject<T> from Remix's useLoaderData<typeof loader> to a function

Encountering a TypeScript error while trying to import JsonifyObject in the Remix 2.9.2 route code below...

Argument of type 'JsonifyObject<IdAndDate>' is not assignable to parameter of type 'IdAndDate'.

Struggling to figure out how to effectively import JsonifyObject:

import { useLoaderData } from "@remix-run/react";

type IdAndDate = {
  id: number;
  date: Date;
};

export default function Component() {
  //
  const idAndDate = useLoaderData<typeof loader>();
  // This part works fine, with idAndDate.date showing as string due to serialization...
  //return (<div>{idAndDate.id}: {idAndDate.date}</div>);

  // However, this encounter an error --
  // "Argument of type 'JsonifyObject<IdAndDate>' is not assignable to parameter of type 'IdAndDate'."
  // -- and I'm unable to figure out how to import JsonifyObject :\
  return <div>{formatIdAndDate(idAndDate)}</div>;
}

export function loader(): IdAndDate {
  return { id: 42, date: new Date() };
}

function formatIdAndDate(idAndDate: IdAndDate): string {
  return `${idAndDate.id}: ${idAndDate.date}`;
}

Attempted solution:

import { JsonifyObject } from "@remix-run/server-runtime/dist/jsonify"

Resulting in the error:

The module '"@remix-run/server-runtime/dist/jsonify"' declares 'JsonifyObject' locally, but it is not exported.

I am at a loss since it is not externally exported either.

Avoiding the usage of as IdAndDate to preserve the recognition by JsonifiyObject that the date is serialized as a string.

(Acknowledging the simplicity of the example, the real scenario involves more intricate logic that warrants browser-side processing.)

Searching for alternatives or possible oversights regarding the availability of JsonifyObject elsewhere.

Answer №1

Make sure to incorporate the json helper in your loader function.

return json({ id: 42, date: new Date() })

When utilizing the useLoaderData function in your UI component, you will receive data of type JsonifyObject.

NOTE: It's possible I misinterpreted your query initially.

To obtain the serialized type, employ the SerializeFrom type helper.

type SerializedIdAndDate = SerializeFrom<IdAndDate>

// alternatively

type SerializedIdAndDate = SerializeFrom<typeof loader>

Answer №2

If anyone is looking for a solution with working code based on the suggestion provided in the accepted answer, this might be helpful:

import { useLoaderData } from "@remix-run/react";
import { SerializeFrom } from "@remix-run/node";

type IdAndDate = {
  id: number;
  date: Date;
};

export default function DisplayComponent() {
  const idAndDate = useLoaderData<typeof loader>();
  return <div>{formatIdAndDate(idAndDate)}</div>;
}

export function loader(): IdAndDate {
  return { id: 42, date: new Date() };
}

function formatIdAndDate(idAndDate: SerializeFrom<IdAndDate>): string {
  return `${idAndDate.id}: ${idAndDate.date}`;
}

For those interested in another approach addressing Joe's concern as mentioned in the comments of the accepted answer, the following code block provides an alternative:

This second version converts the serialized object back to its original data type by adjusting any changes made during serialization process back to their original values. In the example given, only the Date attribute requires adjustment.

import { useLoaderData } from "@remix-run/react";

type IdAndDate = {
  id: number;
  date: Date;
};

export default function DisplayComponent() {
  const serializedIdAndDate = useLoaderData<typeof loader>();
  const idAndDate = { id: serializedIdAndDate.id, date: new Date(serializedIdAndDate.date) };
  return <div>{formatIdAndDate(idAndDate)}</div>;
}

export function loader(): IdAndDate {
  return { id: 42, date: new Date() };
}

// now, this function works with the original unserialized type
function formatIdAndDate(idAndDate: IdAndDate): string {
  return `${idAndDate.id}: ${idAndDate.date}`;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The module 'crypto-js' or its corresponding type declarations cannot be located

I have a new project that involves generating and displaying "QR codes". In order to accomplish this, I needed to utilize a specific encoder function from the Crypto library. Crypto While attempting to use Crypto, I encountered the following error: Cannot ...

show additional worth on the console

Just starting out with JavaScript. Trying to display additional values in the console. Uncertain about how to access add-ons. Can anyone help me troubleshoot? Here is my code snippet below: https://jsfiddle.net/6f8upe80/ private sports: any = { ...

What is the best way to execute a function that retrieves data from a MySQL query and then sends it back as a result in Express.js?

How can I refactor my code to efficiently call a function that returns the result of a MySQL query and send it back in an Express.js response? I am attempting to streamline my SQL queries by exporting them into individual functions to eliminate duplicatio ...

What is the reason for using 'Input' as a type instead of referring to it as a value? TS 2749

The file format is correct as .tsx, however, there seems to be an issue with using HTMLInputElement instead of Input. In my opinion, it should be Input since it relates to the assigned value. Can you help identify the problem in the code snippet below at l ...

Error: Attempting to modify the ip property of an #<IncomingMessage> object that is read-only

Currently, I am in the process of developing a middleware that is intended to assign the user's IP address based on the cloudflare header provided. This method has worked successfully on previous projects of mine, but now it seems to be encountering i ...

Navigating to the next page on a dynamic component in Angular 5 by

I'm uncertain if this scenario is feasible, but I have a page that fetches a list of items from an external API. There are currently 5 elements on the page, each acting as a link to its individual dynamically generated page through query strings. For ...

Tips for accessing data from a local JSON file in your React JS + Typescript application

I'm currently attempting to read a local JSON file within a ReactJS + Typescript office add-in app. To achieve this, I created a typings.d.ts file in the src directory with the following content. declare module "*.json" { const value: any; ex ...

Retrieve the object property based on an array of indices

I am looking to create a function that can retrieve a specific property of an object based on an array of property names const getObjectProperty = (arr: string[], object: any) { // This function should return the desired object property } Expected Outco ...

Is it possible to capture user input using a rich text editor such as Quill and save the data as a .json file by sending a POST request?

My website features a sophisticated text editor known as ngx-quill, where users can input their content. I am currently working on a project that requires me to generate a JSON file containing user input and then submit this JSON file. I am seeking guidan ...

What method is the easiest for incorporating vue.js typings into a preexisting TypeScript file?

I currently have a functional ASP.NET website where I'm utilizing Typescript and everything is running smoothly. If I decide to incorporate jQuery, all it takes is running npm install @types/jQuery, and suddenly I have access to jQuery in my .ts file ...

Google Maps on Angular fails to load

I'm currently working on integrating AGM into my Ionic 2 project. app.module.ts ... import { AgmCoreModule } from '@agm/core'; import { DirectionsMapDirective } from '../components/directions-map'; @NgModule({ declarations: [ ...

The MaxDuration feature for a 5-minute time limit is malfunctioning on the Serverless Pro Plan, resulting in a 504 ERROR on

I am currently using Next.js@latest with App Directory My application is hosted on Vercel I'm experiencing a 504 error from Vercel and I'm on the pro plan. My serverless functions are set to run for up to 5 minutes, but usually, they only take ...

Is it possible to create a single model with different variations, each with specific required fields?

If you're working with our API, you'll likely need to create an Order. While the order model remains consistent across different endpoints, the required fields may vary: For a POST request, only a few fields are required. With a PATCH request, ...

The error message related to TupleUnion in TypeScript is indicating that the depth of type instantiation may be too deep and could

Recently, I've been delving into a TypeScript utility type known as TupleUnion. This useful type came to my attention through a fascinating Twitter post, and I've observed it being utilized in various Stack Overflow solutions. Here's how the ...

Encountering a getStaticProps error while using Typescript with Next.js

I encountered an issue with the following code snippet: export const getStaticProps: GetStaticProps<HomeProps> = async () => { const firstCategory = 0; const { data }: AxiosResponse<MenuItem[]> = await axios.post( ...

Tips for resolving the 'JSX is not defined no-undef' error post TypeScript 4.4.2 update

Upon upgrading to TypeScript 4.4.2 from TypeScript 3.8.2, I have encountered numerous errors such as error 'x' is not defined no-undef. For instance, one of the errors is error 'JSX' is not defined no-undef. Upon closer inspection, most ...

Calling a typed function with conditional types in Typescript from within another function

In my attempt to create a conditional-type function, I stumbled upon this question on Stack Overflow. Unfortunately, it seems that the approach doesn't work well with default values (regardless of where the default value is placed). Following the advi ...

Experiencing problems with React createContext in Typescript?

I've encountered a strange issue with React Context and Typescript that I can't seem to figure out. Check out the working example here In the provided example, everything seems to be working as intended with managing state using the useContext ...

Are optional parameters in TypeScript distinct from parameters that have the ability to be undefined?

Is there a distinction between the following two code snippets? function sayHello(name?: string) { if (name) { return 'Hello ' + name; } return 'Hello!'; } and function sayHello(name: string | undefined) { if (name) { return &apo ...

Attempting to adhere to the prescribed Cypress tutorial is resulting in various errors related to being "compiled under '--isolatedModules'"

I am new to using Cypress and I have been following the helpful tutorial on testing your first application. However, I have encountered some compiler issues in the third section. Following the instructions, I created a custom command but I am receiving th ...