Using React and TypeScript together can lead to issues when trying to use union keys as an index

I've implemented a hook using useState and the delete method to effectively manage my form values.

const [values, setValues] = useState<tAllValues>({});

The values stored include:

{
  name: 'Andrew',
  age: 34,
  avatar: [{
    name: 'avatar.png',
    size: 45234,
    ...
  }]
}

These values can originate from various forms, hence they are assigned the tAllValues type which is a union of all form types.

type tForm1 = { name: string; age: number; };
type tForm2 = { avatar: File };

type tAllValues = tForm1 | tForm2;

A delete method is necessary for removing files. Files are standard objects within the values, and here's how the deletion process works:

const deleteFile = (fileId: string, fieldName: KeysOfUnion<tAllValues>) => {
    const fieldValue = values[fieldName];
    const filteredFiles = fieldValue.filter((value) => value.id !== fileId);
    setValues({ ...values, [fieldName]: filteredFiles });
};

The fieldName parameter is specified as KeysOfUnion because it must be one of the keys from tAllValues, which leads to an issue.

export type KeysOfUnion<T> = T extends any ? keyof T : never;

Even though fieldName should be 'name' or 'age' or 'avatar', TypeScript shows an error:

 Element implicitly has an 'any' type because expression of type '"name" | "age" | "avatar"' can't be used to index type 'tAllValues'.Property 'name' does not exist on type 'tAllValues'.ts(7053)

This error occurs possibly due to the absence of 'name' in tForm2 type but present in tForm1 type.

Is there a solution in TypeScript to address this issue?

Answer №1

Instead of accepting all keys of the union, consider only accepting the keys of the specific object you are working with. Simplify the function by passing in values as a parameter and then using generics to determine the type of v.

const deleteFile = <T extends tAllValues>(v: T, fileId: string, fieldName: keyof T) => {
  const fieldValue = v[fieldName];
  const filteredFiles = fieldValue.filter((value) => value.id !== fileId);
  //^ ERROR: Property 'filter' does not exist on type 'T[keyof T]'
};

However, there is still an error as any fieldValue can be used which may not return an array. To solve this, check if it is an array before proceeding.

if (Array.isArray(fieldValue)) {
  const filteredFiles = fieldValue.filter((value) => value.id !== fileId);
}

Playground Link

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

How to iterate through properties declared in an Interface in Angular 12?

Before Angular 12, this functioned properly: export interface Content { categories: string[] concepts: Topic[] formulas: Topic[] guides: Topic[] } //this.content is of type Content ['formulas', 'concepts'].forEach(c =&g ...

Navigating to the previous page in a Next.js 14 application with the App Router

Recent discussions have mainly focused on the Pages router. I am aware that with react router, I can achieve the following: const history = useHistory(); const { pathname } = useLocation(); history.push('/', { from: pathname }) Subsequently, I ...

Where is the appropriate location to insert a <script> tag in NextJs?

I am facing a challenge in my NextJs application when trying to include the <script> code. I attempted to add it in a .js file but it did not work as expected. In traditional React applications, we typically use the index.html file to incorporate sc ...

Issue resolved: Mysterious fix found for background images not displaying in NextJS React components

I am having trouble displaying a background image on an element in NextJs using Typescript and Tailwind. I do not believe it is a TypeScript issue since I am not receiving any errors or IntelliSense warnings. Below is the code I am working with: var classn ...

Is there a way for me to retrieve the bodyHeight attribute of ag-grid using public variables or data?

Working on a project using ag-grid community react. The main feature is a scrollable section filled with data, which can range from one piece to millions of pieces. I'm also incorporating a footer component for the grid that needs to adjust its height ...

Step-by-step guide on applying a universal CSS class to every component within an application

I am in the process of building a multilingual react application and I am looking for a solution to dynamically apply certain CSS styles to most components based on the chosen language. I am seeking something akin to direction-rtl and direction-ltr, whic ...

Is there a way to identify the accurate or incorrect array element and modify the component color accordingly?

Upon reviewing the question alternatives, I encountered a problem where clicking on one of the buttons correctly indicated whether it was the correct or incorrect answer by changing its color. However, the issue is that all buttons are being affected by th ...

Checking React props using Jest and Enzyme - A simple guide

Trying to understand React testing, I came across two files: Button.js and Button.test.js The code below contains the question along with comments: // Button.js import React from 'react'; import { string, bool, func } from 'prop-types&apos ...

Adjust the dimensions of the react-dropdown-tree-select element to better fit your needs

Hey there, I'm a beginner web developer currently working on a tree-based dropdown menu. Check out the documentation here To see it live in action, visit the example here I'm trying to adjust the height and width of the "Search/DropDown bar" in ...

Using Angular: How to set the index value from a dropdown to a local variable after a button is clicked

Can someone please provide guidance on how to assign the index value (i = index) to EmployeeIndex: any; after a button click event? Your suggestions are greatly appreciated. Here is my code: HTML <select class="form-control" [(ngModel)]="EmployeeNam ...

script code to limit selection of dates within a predefined range

I'm seeking assistance to limit my customers from selecting a date beyond 10 days in advance. Although I previously had a code that functioned properly when there were more than 10 days left in the current month, it is now ineffective. This is becaus ...

Using environment variables, the progression typically goes from Heroku to Docker to Nginx to React

I am currently managing a React application that was created using create-react-app. It is being hosted on Nginx within a Docker container on Heroku. The Docker file configuration I have set up looks like this: # setting up the build environment FROM node ...

Typical ClassIdentifier using Material UI

I have come across similar questions and answers, but due to the MaterialUI update where @mui/styles is deprecated, I didn't fully grasp the concept. As per the MUI docs, we can create custom styles using the sx prop, like this: <Typography varian ...

Enhance React scrollbar functionality without relying on third-party dependencies

Currently working on enhancing the appearance of the scrollbar within my ReactJS project. Specifically, I am aiming for a design similar to this example: https://i.stack.imgur.com/2Q0P4.png Experimented with CSS properties like -webkit-scrollbar, -webki ...

Error: Serialization of circular structure to JSON not possible in Next.js

I am currently working on creating an API in Next.js to add data into a MySQL database. The issue I am facing is related to a circular reference, but pinpointing it has proven to be challenging. It's worth mentioning that Axios is also being utilized ...

What purpose does the class serve in typescript?

This is a unique version of app.component.ts in the Angular Tour of Hero tutorial. import { Component } from '@angular/core'; export class Superhero{ name : string; id : number; } const SUPERHEROES : Superhero[] = [ {name : 'Wonder ...

The result of comparing with `instanceof` in TypeScript

class Department { name: string; constructor(n: string) { this.name = n; } describe(this: Department){ console.log('department: ' +this.name); } } const frontend = new Department('frontend'); frontend.describe(); con ...

Troubleshooting the Issue with Conditional Rendering in Nextjs & TypeScript

Struggling with rendering a component conditionally. I have a drawHelper variable and a function to toggle it between true and false. The component should render or not based on the initial value of drawHelper (false means it doesn't render, true mean ...

The functionality of WrapAll is not functioning properly in React JS

$('p').wrapAll($('<div class="wrapper"></div>')); .wrapper { background: #EEE; margin: 10px; padding: 5px; border: 1px solid black; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery. ...

I am struggling to properly display filtered data on my screen

Utilizing MUI to showcase mock data from a JSON file in a table. An input field triggers an onChange event, calling a function to filter data based on the input and display it in the table. The filtering works, but both the filtered data and the old data ...