Why is the IDE giving this error when the value is clearly available in one of the interfaces used? The interface for the context action uses two interfaces to specify one of the types of data in the dispatch action. The IDE is giving me this error when I try to update the data in the reducer.
Property 'firstName' does not exist on type 'iCards | iSearch'. Property 'firstName' does not exist on type 'iCards'.
Here is the interface for the context action and the interfaces used to create it.
interface iAction{
type: 'search' | 'show all';
payload: iSearch | iCards
}
interface iSearch {
firstName: string;
lastName: string;
country: string;
}
interface iCards {
searchText: string;
searchParams: string[];
}
Here is the reducer code.
export default function CardsReducer(initialData: iInitialData, action: iAction) {
const data = structuredClone(initialData); <-- initialData.firstName is already set to an empty string
data.firstName = action.payload.firstName; <--- IDE gives me the error here.
return data
}
firstName is in the iSearch interface and iInitialData interfaces, so why is it telling me it doesn't exist?
Typescript gives an error because payload
may or may not have a property firstName
.
If both - iSearch
and iCards
would have a property firstName
, then it would not complain.
You can fix this by refactoring iAction
interface to union type. Like this:
interface iSearchAction {
type: 'search';
payload: iSearch;
}
interface iShowAllAction {
type: 'show all';
payload: iCards;
}
type iAction = iSearchAction | iShowAllAction;
interface iSearch {
firstName: string;
lastName: string;
country: string;
}
interface iCards {
searchText: string;
searchParams: string[];
}
export default function CardsReducer(initialData: iInitialData, action: iAction) {
const data = structuredClone(initialData);
if (action.type === 'search') {
/**
* Here typescript already knows that payload is of type iSearch,
* because if action's type is 'search', payload's type is 'iSearch' due to type narrowing
* Read more about type guards.
*/
data.firstName = action.payload.firstName;
}
return data;
}
P.S: You haven't specified type of iInitialData
in your given example, I assume there's no issue with it.