Home > Mobile >  Unable to render Component dynamically through Object.entries
Unable to render Component dynamically through Object.entries

Time:02-03

I'm trying to reduce my code and render a series of MUI rows through a loop and Object.entries. Though each time that I try to extract the value of a sperate Object, I get TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Chalk'.   No index signature with a parameter of type 'string' was found on type 'Chalk'.

rowLabels and chalk keys match.

    const ConfigureRowValue = () => {
        const rowLabels = {
            sling: 'Load',
            bump: 'Bump Priority',
            equipment: 'Key Equipment',
            w: 'Key W',
            notes: 'Notes',
        };
        for (const [key, value] of Object.entries(rowLabels)) {
            return (
                <>
                    <ChalkCardDataRow
                        label={`${value}`}
                        value={`${chalk[key]}`}
                    />
                </>
            );
        }
    };
*****************************************
    type ChalkCardDataRowProps = {
        label: string;
        value: string | null;
    };
    
        export const ChalkCardDataRow = ({ label, value }: ChalkCardDataRowProps) => {
            return (
                <TableRow>
                    <TableCell style={{ borderBottom: 'none' }}>{label}:</TableCell>
                    <TableCell
                        align={'right'}
                        style={{ borderBottom: 'none' }}
                    >
                        <Typography color='grey'>{value ?? '-'}</Typography>
                    </TableCell>
                </TableRow>
            );
        };

If I explicitly insert the component multiple times it works but causes too much code duplication. i.e:

<ChalkCardDataRow
                                    label={'Sling Load'}
                                    value={chalk.sling}
                                />

                                <ChalkCardDataRow
                                    label={'Bump Priority'}
                                    value={chalk.bump}
                                />

CodePudding user response:

Unfortunately Object.entries return type gives the keys as string, instead of keyof object. See ms/TS#12253 for explanations on this design choice.

The usual workaround is to use a type assertion in this case, since you are sure that both objects have the same keys: chalk[key as keyof typeof rowLabels]

Playground Link


Another solution would be to use ts-extras/objectEntries:

A strongly-typed version of Object.entries().

import {objectEntries} from 'ts-extras';

for (const [key, value] of objectEntries(rowLabels)) {
  result.push(
    <>
      <ChalkCardDataRow
        label={`${value}`}
        value={`${chalk[key]}`} // Okay
      />
    </>
  );
}

Playground Link

  • Related