I have an action in my redux toolkit that's attempting to set some state. Relevant code below:
interfaces
export interface ProposalTag {
id: number;
name: string;
hex: string;
color: string;
}
export interface ProposalSelectedTag {
proposal_id: number;
proposal_tag_id: number;
}
redux
import { ProposalTag, ProposalSelectedTag } from '../../types/proposalTags';
interface ProposalTagsSlice {
proposalTags: ProposalTag[];
selectedProposalTags: ProposalTag[];
}
const initialState: ProposalTagsSlice = {
proposalTags: [],
selectedProposalTags: [],
};
const matchTags = (
selectedTags: ProposalSelectedTag[],
proposalTags: ProposalTag[],
): ProposalTag[] => {
const tags = selectedTags.map((selectedTag: ProposalSelectedTag) => {
return proposalTags.find(proposalTag => proposalTag.id === selectedTag.proposal_tag_id);
});
return tags ?? [];
};
export const proposalTagsSlice = createSlice({
name: 'proposalTags',
initialState,
reducers: {
setSelectedProposalTags: (state, action: PayloadAction<ProposalSelectedTag[]>) => {
if (state.proposalTags === undefined) return;
state.selectedProposalTags =
action.payload === null ? [] : matchTags(action.payload, state.proposalTags);
},
},
});
The goal of matchTags
is to convert the payload of ProposalSelectedTag[]
to ProposalTag[]
. So in theory, ProposalSelectedTag.proposal_tag_id
The type errors I get back are the following:
Did I lose typing somewhere in matchTags
?
CodePudding user response:
That's because Array.prototype.find
will return undefined
if the element is not found.
If you are sure that the item exists in the list, you can make an assertion that will calm TypeScript down.
const tags = selectedTags.map((selectedTag: ProposalSelectedTag) => {
const item = proposalTags.find(proposalTag => proposalTag.id === selectedTag.proposal_tag_id);
if (!item) throw new Error('item was not found')
return item
});
You can also use !
const tags = selectedTags.map((selectedTag: ProposalSelectedTag) => {
return proposalTags.find(proposalTag => proposalTag.id === selectedTag.proposal_tag_id)!;
});
Or you can set a default value
const tags = selectedTags.map((selectedTag: ProposalSelectedTag) => {
return proposalTags.find(proposalTag => proposalTag.id === selectedTag.proposal_tag_id) ?? 10;
});