Utilizing precise data types for return values in React hooks with Typescript based on argument types

I developed a react hook that resembles the following structure:

export const useForm = <T>(values: T) => {
  const [formData, setFormData] = useState<FormFieldData<T>>({});

  useEffect(() => {
    const fields = {};
    for (const key in values) {
      const value = values[key];
      fields[key] = {
        value,
        errorMsg: '',
      };
    }
    setFormData(fields);
  }, []);

  return {
    formData,
  };
};

This hook accepts an object with various fields and their default values, for example:

  const { formData } = useForm({
    stringField: '',
    numberField: 1,
    booleanField: false,
  });

The hook then uses these keys and default values to construct and return an object called formData:

{
  stringField: {
    value: '',
    errorMsg: '',
  },
  numberField: {
    value: 1,
    errorMsg: '',
  },
  booleanField: {
    value: false,
    errorMsg: '',
  },
}

To correctly type the formData, I defined a type named FormFieldData. This type takes in the generic type parameter passed to the hook and generates a type for formData based on the provided keys and values:

export type FormField<T> = {
  errorMsg: string;
  value: T;
};

export type FormFieldData<T> = {
  [K in keyof T]: FormField<T[keyof T]>;
};

The issue arises when each value in the field object within formData turns into a union type of all the different types included in the original hook call. For instance, if we take the earlier example, formData.stringField.value would have a type of string | number | boolean.

What I expect is for the type of each field's value property to match the exact type of the original value assigned to that field in the initial hook call. Therefore, formData.stringField.value should be of type string, and formData.numberField.value should be of type number.

Am I overlooking something here?

How does T[keyof T] result in a union of all types present in the generic object?

Update

I resolved this issue by modifying the FormFieldData type to:

export type FormFieldData<T> = {
  [K in keyof T]: FormField<T[K]>;
};

Answer №1

To resolve the issue, I made a modification to the FormFieldData by adjusting its type definition as shown below:

export type FormFieldData<T> = {
  [K in keyof T]: FormField<T[K]>;
};

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 script ceases to function once the page is loaded from a JSON file

I'm facing an issue on my shopping website where the items and products are loaded from a JSON file. The problem is that once the page has loaded, the script fails to work properly. If the items take a little longer to load on the page, the script doe ...

The depth buffer in Webgl FrameBuffer is not being cleared properly

Currently, I am working on developing a 2D sprite renderer that utilizes render textures for custom compositing. However, I have encountered an issue where the depth buffer on the FrameBuffer is not clearing properly. Due to this, all the sprites leave a p ...

After the assignment, TypeScript reordered the elements of the array

Dealing with an array of objects for use in a ngFor loop has presented a challenge. The issue arises when the order that was initially set for the array changes unexpectedly due to JavaScript manipulation. Originally, the array is ordered as expected when ...

Dealing with multiple input fields that are generated using the map method in combination with react-redux

I am working on a project where I have a product list in JSON format stored in json-server. I am using React-Redux to fetch the data and render it in a table. Additionally, I have an input field where users can enter the quantity of each product. I need to ...

Is it possible to save an entire webpage that infinitely scrolls without actually manually scrolling through it?

I'm dealing with a webpage that has infinite downward scrolling. I tried automating the scrolling, but eventually the page became too large to continue scrolling. To fix this, I manually removed some DIV blocks from the source code which decreased the ...

Tips for modifying CSS when a user scrolls beyond a specific div

Currently, I am working on implementing a scroll function that dynamically moves elements based on the user's scrolling behavior. The code I have written works to some extent and successfully moves the elements. However, my goal is to create a list o ...

Is CDATA insertion automatic in JavaScript within Yii framework?

Currently I am working with Yii and have noticed that whenever I insert any JavaScript code, it is automatically encapsulated in CDATA. I am curious as to why this is happening. Will there be any issues if I were to remove the CDATA tags, considering that ...

Uploading a file from a React contact form using Axios may result in S3 generating empty files

I have set up a test contact form that allows users to upload image attachments. The presignedURL AWS Lambda function is working properly After uploading, the image file (blob) appears as an image in the HTML, indicating successful addition Upon posting t ...

Error occurred while making a request in React using Axios: TypeError - Unable to retrieve the 'token' property as it is undefined

After successfully receiving a token from logging in with React Redux, I attempted to authorize it using the token. However, an error occurred stating Axios request failed: TypeError: Cannot read property 'token' of undefined. The token is stored ...

Is there a way to conceal the contents of a page until all the images have finished loading?

I'm currently working on improving the performance of a website that is loading very slowly. I have already reorganized, compressed and minified the JavaScript and CSS files, but the main issue seems to be with the images. The site contains large imag ...

"Learn to easily create a button within a table using the powerful functionality of the dataTable

I need to add a button to each row in a table. I managed to achieve this with the code below, but there's a problem - every time I switch between pages, the button keeps getting added again and again. It seems like the button is generated multiple tim ...

What steps should I follow to track an event using Firebug?

When I examine the element, how can I discover all of the events that are attached to it? ...

Harnessing the power of express middleware to seamlessly transfer res.local data to various routes

I am in the process of implementing a security check middleware that will be executed on the specific routes where I include it. Custom Middleware Implementation function SecurityCheckHelper(req, res, next){ apiKey = req.query.apiKey; security.securi ...

Adjusting the iframe for a side navigation with multiple dropdown options

I have a file called index.html that contains two dropdown containers and an iframe. The first dropdown container works with the iframe, but the second one does not. Can anyone help me fix this issue? I am having trouble understanding the script for chang ...

Ajax appends a single row, not an entire array

My ajax function is retrieving an array of data from the backend, but when I try to display it in the blade, only one row appears instead of multiple rows. List of Problems Only 1 row is appended by ajax The select option is empty when the results return, ...

What is the best way to prevent a draggable div from moving past the edge of the viewport?

My situation involves a draggable div that functions as a popup window when a specific button is clicked. However, I noticed that dragging the div to the end of the viewport allows me to drag it out of the visible area, causing the body of the page to expa ...

The share-modal.js file is throwing an error because it is unable to read properties of null, particularly the 'addEventListener' property, at

I encountered an error that I want to resolve, but it's proving to be quite challenging. Despite extensive searching on Google, I haven't found a solution yet. Uncaught TypeError: Cannot read properties of null (reading 'addEventListener&apo ...

Threejs file exporter from Blender generating corrupted files

My Blender model seems to be causing issues: After using the threejs exporter in Blender 2.7, the exported json file contains numerous null or 0 values: { "metadata": { "formatVersion" : 3.1, "generatedBy" : "Blender 2.7 Exporter", ...

Image not located: 404 error in JavaScript

I am currently working with JavaScript and have encountered an issue. I have an array of objects that contain various data such as id, title, price, and image. I need to retrieve this data from the array in order to display it. While I am able to successfu ...

What is the process for automatically initiating a service when importing a module in Angular?

I am curious about how I can automatically run a service within a module upon importing it, without the need for manual service injection and execution. This functionality is similar to how the RouterModule operates. @NgModule({ imports: [ Browser ...