I don't understand why I'm getting this error:
Argument of type '{ id: string; }' is not assignable to parameter of type 'never'.
... at the line const index = state.sections.findIndex((section) => section.id === id);
in the following portion of my Vue store:
import { MutationTree, ActionTree, GetterTree } from 'vuex';
interface section {
id: string;
section_header: string;
section_body: string;
sectionItems: any;
}
interface sections extends Array<section>{}
export const state = () => ({
sections: [
{
id: '1',
section_header: 'lorem',
sectionItems: []
},
{
id: '2',
section_header: 'ipsum',
sectionItems: []
}
]
});
type EditorState = ReturnType<typeof state>;
export const mutations: MutationTree<EditorState> = {
ADD_SECTION_ITEM(state, id) {
const index = state.sections.findIndex((section) => section.id === id);
const sectionItem = {
id: randomId()
}
state.sections[index].sectionItems.push(sectionItem);
},
};
I think you need state.sections.push(sectionItem) instead of state.sections[index].sectionItems.push(sectionItems).
I would say you probably need to type your sectionItems:
interface SectionItem {
id: string
}
interface Section {
id: string;
section_header: string;
section_body?: string;
sectionItems: SectionItem;
}
interface State {
sections: Section[]
}
export const state = (): State => ({
sections: [
{
id: '1',
section_header: 'lorem',
sectionItems: []
},
{
id: '2',
section_header: 'ipsum',
sectionItems: []
}
]
});
type EditorState = ReturnType<State>;
export const mutations: MutationTree<EditorState> = {
ADD_SECTION_ITEM(state, id) {
const index = state.sections.findIndex((section) => section.id === id);
const sectionItem = {
id: randomId()
}
state.sections[index].sectionItems.push(sectionItem);
},
};
Because, when you don't specify the type of sectionItems, typescript looks at the sectionItems that you initialised in your state (which are equal to []) and cannot identify the type of elements that should be in this array.
So you define it. Also, section_body should be optional because you it's not there in all your examples. Interface names should be capitalised in typescript.
Also, I do not think you need the sections interface. if you want to type something as an array of an interface, just use section[] as the type, like you would do string[].
Finally, this is up to you but I would advise against using different naming conventions in your interfaces (and in your code in general): section_body is snake_case and sectionItems is camelCase, it's usually better to stick to one and keep it in all the code.
Edited, You need to type the "state" using an interface State that describes it.
Additionally, I do not have much experience with Vuex specifically, but they seem to indicate a specific way to use it with typescript, that is different than what you are doing: vuex docs here
When you don't provide a type for a value -- your function's return value, in this case -- TypeScript tries to narrow it down to the most accurate type it can. Since your returned object's sections' item arrays are always empty, it infers them as never[] (type[] is an alias for Array<type>); an array that can't actually contain any values. You can see this in the following snippet:
const functionReturningEmptyArray = () => ({ items: [] });
type EmptyArray = ReturnType<typeof functionReturningEmptyArray>;
// type EmptyArray = { items: never[] }
One way you can solve this is using the section interface you created to specify the return type of state.
export const state = (): { sections: Array<section> } => ({
sections: [
{
id: '1',
section_header: 'lorem',
sectionItems: []
},
{
id: '2',
section_header: 'ipsum',
sectionItems: []
}
]
});
The colon after the empty parentheses on the first line specifies the function's return type. I've inlined the object type in this case as it only has one property, but if your state is more complex, or if you just prefer the readability, you can extract it to a separate type and reference that as the return type;
interface MyState {
sections: Array<section>;
}
export const state = (): MyState => ({
sections: [
{
id: '1',
section_header: 'lorem',
sectionItems: []
},
{
id: '2',
section_header: 'ipsum',
sectionItems: []
}
]
});
At this point, TypeScript will throw an error on your returned value, because your section interface specifies that the object should also have a section_body property, which is missing in your returned sections array. To fix this, you can either give each object in the array a section_body property, or modify the interface to match the fact that the property may or may not exist;
interface section {
id: string;
section_header: string;
section_body?: string;
sectionItems: any;
}
Your store should now be error-free, but to have a more type safe sectionItems property, you can also change it from any to Array<any>, or use a more specific object type if you know what the section items will look like beforehand.