I have a react component that takes in data of type EncumbranceData[]
and restructures that data before mapping through it. This restructuring involves creating an empty object of type EncumbrancesByType
and creating keys and values for it based on encumbranceData
However, I keep getting an "Object possible undefined" error where it says encumbrancesByType[e.type].push(e.suite)
. I don't understand how this could be undefined, as none of the fields on these types are optional. This component will always receive data of type EncumbranceData
that will always have a type, id, and suite. EncumbranceData
cannot be undefined. The object starts as an empty one, but each iteration through the forEach
method should initialize each key with a truthy empty array.
How can the object possible be undefined, then, at the push(e.suite)
statement?
I can get it to work by just using a bunch of optional operators (encumbrancesByType?.push()
), but I feel like that defeats the point of type safety.
type EncumbranceData = {
id: string;
suite: string;
type: string;
};
interface EncumbrancesByType {
[key: string]: string[];
}
type EncumbranceAlertByTypeProps = {
id: string;
suites: string[];
type: string;
};
const EncumbranceAlertByType: React.FC<EncumbranceAlertByTypeProps> = ({ id, suites, type }) => {
const renderSuites = suites.map((s) => <span>{s}</span>);
return (
<div>
<div>{type}</div>
{renderSuites}
</div>
);
};
type ConflictingEncumbrancesAlertProps = {
encumbranceData: EncumbranceData[];
isOpen: boolean;
onContinue(): void;
onCancel(): void;
suiteIdsToCheck: string[];
encumbranceTypesToConsider?: EncumbranceType[];
};
const ConflictingEncumbrancesAlert: React.FC<ConflictingEncumbrancesAlertProps> = ({
encumbranceData,
isOpen,
onContinue,
onCancel,
suiteIdsToCheck,
encumbranceTypesToConsider,
}) => {
const encumbrancesByType: EncumbrancesByType = {}
encumbranceData.forEach((e) => {
if (!encumbrancesByType[e.type]) encumbrancesByType[e.type] = [e.suite]
else encumbrancesByType[e.type].push(e.suite)
})
const encumbrancesContent = Object.keys(encumbrancesByType).map((type) => (
<EncumbranceAlertByType suites={encumbrancesByType[type]} type={type} />
));
return <div>{encumbrancesContent}</div>;
};
export default ConflictingEncumbrancesAlert;
CodePudding user response:
You likely have the noUncheckedIndexedAccess
rule enable in your tsconfig
. When you have this rule the compiler will always complain on unchecked index access.
Also, TS won't narrow down (remove the undefined
) on index access. In order to have the compiler do that, you'll have to use an intermidiate variable.
encumbranceData.forEach((e) => {
const foo = encumbrancesByType[e.type]; // intermediate variable
if (foo) {
foo.push(e.suite); // ok
}
});