繁体   English   中英

Vue 存储数组声明中的“不能分配给从不类型的参数”TS 错误

[英]"Not assignable to parameter of type never" TS error in Vue store array declaration

我不明白为什么会出现此错误:

'{ id: string; 类型的参数 }' 不可分配给“从不”类型的参数。

...在行const index = state.sections.findIndex((section) => section.id === id);

在我的 Vue 商店的以下部分:

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);
  },
};

我会说你可能需要输入你的sectionItems:

interface SectionItem {
  id: string
}

interface Section {
  id: string;
  section_header: string;
  section_body?: string;
  sectionItems: SectionItem;
}

因为,当您不指定 sectionItems 的类型时,typescript 会查看您在 state(等于 [])中初始化的 sectionItems,并且无法识别应该在此数组中的元素类型。

所以你定义它。 此外, section_body 应该是可选的,因为您的所有示例中都没有它。 接口名称在 typescript 中应大写。

另外,我认为您不需要部分界面。 如果你想输入一个接口数组,只需使用 section[] 作为类型,就像你做 string[] 一样。

最后,这取决于您,但我建议不要在您的界面(以及您的一般代码中)使用不同的命名约定:section_body 是snake_case,sectionItems 是camelCase,通常最好坚持一个并将其保留在所有代码中.

我认为您需要state.sections.push(sectionItem)而不是state.sections[index].sectionItems.push(sectionItems)

当你不提供一个值的类型时——你的函数的返回值,在这种情况下——TypeScript 试图将它缩小到它可以的最具体的类型。 由于您返回的对象的sections项 arrays 始终为空,因此将它们推断为never[]type[]Array<type>的别名); 一个实际上不能包含任何值的数组。 您可以在以下代码段中看到这一点:

const functionReturningEmptyArray = () => ({ items: [] });
type EmptyArray = ReturnType<typeof functionReturningEmptyArray>;
// type EmptyArray = { items: never[] }

解决此问题的一种方法是使用您创建的section接口来指定state的返回类型。

export const state = (): { sections: Array<section> } => ({
  sections: [
    {
      id: '1',
      section_header: 'lorem',
      sectionItems: []
    },
    {
      id: '2',
      section_header: 'ipsum',
      sectionItems: []
    }
  ]
});

第一行空括号后面的冒号指定函数的返回类型。 在这种情况下,我已经内联了 object 类型,因为它只有一个属性,但是如果您的state更复杂,或者您只是更喜欢可读性,您可以将其提取为单独的类型并将其引用为返回类型;

interface MyState {
    sections: Array<section>;
}

export const state = (): MyState => ({
  sections: [
    {
      id: '1',
      section_header: 'lorem',
      sectionItems: []
    },
    {
      id: '2',
      section_header: 'ipsum',
      sectionItems: []
    }
  ]
});

此时, TypeScript 将在您的返回值上抛出错误,因为您的section接口指定 object 还应该具有section_body属性,该属性在您返回的sections数组中缺失。 要解决此问题,您可以为数组中的每个 object 赋予section_body属性,或者修改接口以匹配该属性可能存在或不存在的事实;

interface section {
  id: string;
  section_header: string;
  section_body?: string;
  sectionItems: any;
}

您的商店现在应该没有错误,但要拥有更安全的sectionItems属性,您还可以将其从any更改为Array<any> ,或者如果您事先知道部分项目的外观,则使用更具体的 object 类型.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM