The Vue store array declaration triggers a TS error stating that it is not assignable to a parameter of type never

I'm puzzled as to why this error keeps showing up:

Argument of type '{ id: string; }' is not assignable to parameter of type 'never'.

... appearing at

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

This issue stems from the Vue store snippet below:

import { MutationTree, ActionTree, GetterTree } from 'vuex';

interface segment {
  id: string;
  segment_title: string;
  segment_content: string;
  segmentItems: any;
}

interface segments extends Array<segment>{}

export const state = () => ({
  segments: [
    {
      id: '1',
      segment_title: 'lorem',
      segmentItems: []
    },
    {
      id: '2',
      segment_title: 'ipsum',
      segmentItems: []
    }
  ]
});

type EditorState = ReturnType<typeof state>;

export const mutations: MutationTree<EditorState> = {
  ADD_SEGMENT_ITEM(state, id) {
    const index = state.segments.findIndex((section) => section.id === id);
    const segmentItem = {
      id: randomId()
    }
    state.segments[index].segmentItems.push(segmentItem);
  },
};

Answer №1

When you do not specify a type for a value - such as the return value of your function in this case - TypeScript will attempt to infer the most precise type possible. In situations where the arrays within your returned object's sections are always empty, TypeScript infers them as never[] (type[] is just an alias for Array<type>); indicating an array that cannot hold any values. This can be observed in the code snippet below:

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

To address this issue, one approach is to utilize the section interface that you have defined to explicitly define 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 following the empty parentheses on the initial line declares the function's return type. I have included the object type inline in this instance since it comprises only one property. However, if your state is more intricate or for enhanced readability, you can extract it into a distinct type and refer to 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 juncture, TypeScript will emit an error concerning your returned value because your section interface stipulates that the object must also possess a section_body property, which is absent in your returned sections array. To rectify this, you can either assign a section_body property to each object in the array or adjust the interface to accommodate the possibility of the property being present or absent.

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

Your store should now be free of errors. For a more type-safe sectionItems property, consider changing it from any to Array<any>, or deploying a more specific object type if you have foreknowledge of the appearance of the section items.

Answer №2

In my opinion, the correct approach would be to use state.sections.push(sectionItem) instead of

state.sections[index].sectionItems.push(sectionItems)
.

Answer №3

It is advisable to specify the type for your sectionItems when defining your interfaces:

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

By not specifying the type, TypeScript cannot determine the elements expected in the array based on the initialized values.

It's recommended to capitalize interface names and keep naming conventions consistent throughout the codebase.

You can use section[] as a type instead of creating a separate interface for sections.

Ensure to type the "state" using an interface named State that accurately describes it.

For Vuex with TypeScript, refer to the Vuex documentation for best practices.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on implementing a cordova plugin in a TypeScript cordova application

In my Cordova project, which utilizes Angular and Typescript, I am facing issues with implementing the juspay-ec-sdk-plugin for Cordova. I have explored possible solutions on StackOverflow related to integrating Cordova plugin in an Angular 4 Typescript ...

Discover the position of a div relative to another div using ng-drag-drop

I'm currently working on a web application that allows users to create their own identity cards. For this project, I am incorporating the ng-drag-drop library from https://www.npmjs.com/package/ng-drag-drop. The main goal is to obtain the coordinate ...

Utilizing String.Format in TypeScript similar to C# syntax

Is there a way to achieve similar functionality to String.Format in C# using TypeScript? I'm thinking of creating a string like this: url = "path/{0}/{1}/data.xml" where I can substitute {0} and {1} based on the logic. While I can manually replace ...

Using parameters in NativeScript-Vue

I'm having trouble passing parameters to another route in Nativescript. Every time I try, it shows up as undefined. I am using the nativescript-vue-navigator. On my current screen, I have this function call: this.$navigator.navigate('/map' ...

Ensure that selecting one checkbox does not automatically select the entire group of checkboxes

Here is the code I'm using to populate a list of checkboxes. <label class="checkbox-inline" ng-repeat="item in vm.ItemList track by item.id"> <input type="checkbox" name="item_{{item.id}}" ng-value="{{item.id}}" ng-model="vm.selectedItem" /& ...

Is it possible to loop through a subset of a collection using *ngFor?

Is it possible to iterate through a specific range of elements in a collection using *ngFor? For instance, I have a group of checkboxes with their form control name and label specified as follows: [{id: 'c1', label: 'C1'}, ...] Assum ...

Managing a collection of objects within another object

Consider the following two classes with a focus on simplicity for clarity (no sanity-checking of variables etc): <?php class Person { private $Name; private $Phones = []; // List/array of phone number. function __construct($ ...

Is it possible to use Vue files without relying on NodeJS?

Is it possible to host my app outside of Node.js while still using .vue files and possibly npm as a build system? I don't require backward compatibility, as long as it works on the latest Chrome development version. Are there any examples or tutorial ...

Iterate over the key-value pairs in a loop

How can I iterate through a key-value pair array? This is how I declare mine: products!: {[key: string] : ProductDTO}[]; Here's my loop: for (let product of this.products) { category.products.push((product as ProductDTO).serialize()); } However, ...

Getting the parent from a child in Typescript: Best Practices

Querying: In TypeScript, is it possible to retrieve a parent instance from a child instance? I am aware that casting a child into its parent is a method, however, the child's additional properties still exist in the parent, albeit concealed. Check o ...

Navigating to a randomly generated ID in Firestore using Vue - A Step-by-Step Guide

My app uses Firestore as a backend for posts. On the screen displaying all categories, when a new category is created it's added to the list. When a category is clicked, I use its id as a parameter to navigate to that specific category and show the po ...

Creating a fresh JSON structure by utilizing an established one

I have a JSON data that contains sections and rubrics, but I only need the items for a new listing. The new object named 'items' should consist of an array of all the items. The final JSON output should be sorted by the attribute 'name&apos ...

Higher order components enhance generic components

I'm facing an issue where I want to assign a generic type to my React component props, but the type information gets lost when I wrap it in a higher order component (material-ui). How can I ensure that the required information is passed along? type P ...

Having trouble interpreting sub items with JSON parsing

I'm encountering an issue with parsing and formatting my JSON data correctly. Can anyone provide guidance on how to parse the data accurately in this particular scenario? SOURCE: try { HttpURLConnection conn = (HttpURLConnection) new U ...

Remove an item from an array within Express using Mongoose

{ "_id": "608c3d353f94ae40aff1dec4", "userId": "608425c08a3f8db8845bee84", "experiences": [ { "designation": "Manager", "_id": "609197056bd0ea09eee94 ...

Creating a unified environment variable for Angular 2 and ASP.NET Core MVC: A comprehensive guide

In my ASP.NET Core MVC project, I am utilizing an Angular 2 application. Both the Angular 2 app and the Startup.cs file contain code that is specific to different environments. For example, using http://localhost as the web service URL during development ...

Using Swift to transmit an array as a parameter in a POST request to PHP

As I dive into developing an app using Swift, one of my current tasks involves calling a PHP webservice from the app. Below is the snippet of code for the webservice: // Code snippet for calling PHP webservice // Created by Belal Khan on 12/08/16 import ...

A comprehensive guide to using Reactive Forms in Angular

I need help understanding how FormGroup, FormControl, FormArray work in Angular. The error message I'm encountering is: Type '{ question: FormControl; multi: true; choices: FormArray; }' is not assignable to type 'AbstractControl' ...

The function 'transformArticles' is not recognized as a property of the object 'Article'

I'm encountering an issue with Typescript that I need help understanding. In my code, I have a route where I am importing a class called Article like this: import { Request, Response } from "express"; const appRoot = require("app-root-path"); import ...

Tips for displaying the date in 13-digit Unix Timestamp format using JSpreadSheet

I am faced with a challenge involving data that is stored in Unix Timestamp format, which I need to display as a readable date (e.g. YYYY/MM/DD) in JSpreadSheet ("jspreadsheet-ce"). Currently, the data appears as a 13-digit number and looks unattractive. ...