Solving the 'never' type issue in Vue3 and TypeScript for an empty array reference

I am currently in the process of migrating a component from an old Vue project that relies solely on JavaScript to a TypeScript/Vue project, and I have encountered some obstacles along the way.

<script lang="ts">
import { computed, ref } from "vue";
import { defineComponent } from 'vue'
export default defineComponent ({
setup() {

const todo = ref("");
const todos = ref([]);
let id = 0;
const numberOfCompletedTodos = computed(
  () => todos.value.filter((todo) => todo.completed).length
);
function addTodo() {
  todos.value.push({
    id: id,
    title: todo.value.trim(),
    completed: false,
  });
  todo.value = "";
  id++;
}
function removeTodo(index) {
  todos.value.splice(index, 1);
}
...
...
...
</script>

However, the use of ref([]) is resulting in the following errors:

- Argument of type '{ id: number; title: string; completed: boolean; }' is not 
assignable to parameter of type 'never'.ts(2345)

- Property 'completed' does not exist on type 'never'.

- Parameter 'index' implicitly has an 'any' type.

Answer №1

When using the ref function, it has the ability to determine the type of the value you want to store in the reference that is returned. If you pass in an empty array, the inferred type becomes never[], indicating an array that will never contain any elements. Obviously, this is not the desired outcome. One way to fix this is by initializing the ref with an array containing Todo objects, but this may not be the best approach.

To accurately specify that you intend to store Todos in the array, TypeScript requires a type parameter when calling the ref function. You can achieve this by creating a type or an interface for Todo and passing it like so:

type Todo = {
  id: number;
  title: string;
  completed: boolean;
}

const todos = ref<Todo[]>([]);

Alternatively, you can define the type inline as shown below:

const todos = ref<{ id: number; title: string; completed: boolean }[]>([]);

Answer №2

To streamline the process, I would suggest creating an interface specifically for this purpose. Additionally, utilizing the generic ref<> can simplify things.

ITodoInterface.ts

export interface ITodoInterface {
        id: number;
        title: string;
        completed: boolean;
    }

TodoComponent.vue

<script lang="ts">
import { computed, ref } from "vue";
import { defineComponent } from 'vue'
export default defineComponent ({
    setup() {
        const todo = ref<ITodoInterface|undefined>(undefined);
        const todos = ref<ITodoInterface[]>([]);
        let id = 0;
        const numberOfCompletedTodos = computed(
            () => todos.value.filter((todo) => todo.completed).length
        );
        function addTodoItem() {
            todos.value.push(todo.value);
            todo.value = undefined;
            id++;
        }
        function removeTodoItem(index) {
            todos.value.splice(index, 1);
        }
</script>

Answer №3

While grappling with a similar challenge in my Vue.js project that involved a reactive store, I encountered a snag. Merely incorporating an interface did not do the trick. However, explicitly designating a type using [] as Banana[] turned out to be the key solution.

interface Banana {
  description: string;
}
interface BananaStore {
  bananas: Banana[];
}
export const bananaStore: BananaStore = reactive({
  bananas: [] as Banana[]
})

Hopefully, this insight proves beneficial to your situation. Remember to relish the process. Best of luck!

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

Error: Unable to locate package @babel/preset-vue version 7.1.0

I am currently working on a simple website using Ruby on Rails and Vue.js, but I am running into issues when trying to start the local server. After executing npm run dev in the terminal, I encountered 2 errors: This dependency was not found: * /Users/mu ...

Sending information from a Vue instance to a local Vue component

I am facing an issue with a single Vue Instance containing a local Component as shown below // vue instance for the navbar menu var foo = new Vue({ el: '#custom-header', data: { label1 : 'text1', lable2 : &apos ...

What is the reason behind the file not found error encountered when running Deno with the command "echo hello"?

Exploring Deno's standard library, I encountered an issue with Deno.run - a function designed to create a new subprocess. Here is the example provided in the documentation: const p = Deno.run({ cmd: ["echo", "hello"], }); When I attempt to run ...

Exploring the integration of web components within VuePress

I'm currently working on integrating Stoplight into our vuepress site. This involves implementing a web component called elements-api provided by stoplight. Here's my progress so far: APIStopLight.vue <template> <main class="a ...

A guide on accessing objects from an array in Vue.js

Wondering how to choose an object from an array in Vue.js: When the page loads, the selectTitle() function is triggered. I simply want to select a specific object (for example, i=2) from my 'titleList' array. However, at the moment, I am only re ...

Angular 5 error: Decorators do not support function expressions

I am struggling to compile my angular project using the command ng build --prod The issue arises in the IndexComponent : index.componenent.ts import { Component, OnInit } from '@angular/core'; import { indexTransition } from './index.anim ...

Problem integrating 'fs' with Angular and Electron

Currently, I am working with Angular 6.0, Electron 2.0, TypeScript 2.9, and Node.js 9.11 to develop a desktop application using the Electron framework. My main challenge lies in accessing the Node.js native API from my TypeScript code. Despite setting "com ...

assign data points to Chart.js

I have written a piece of code that counts the occurrences of each date in an array: let month = []; let current; let count = 0; chartDates = chartDates.sort() for (var i = 0; i < chartDates.length; i++) { month.push(chartDates[i].split('-&ap ...

The specified class is not found in the type 'ILineOptions' for fabricjs

Attempting to incorporate the solution provided in this answer for typescript, , regarding creating a Line. The code snippet from the answer includes the following options: var line = new fabric.Line(points, { strokeWidth: 2, fill: '#999999', ...

Unique TypeScript code snippets tailored for VSCode

Is it possible to create detailed custom user snippets in VS Code for TypeScript functions such as: someArray.forEach((val: getTypeFromArrayOnTheFly){ } I was able to create a simple snippet, but I am unsure how to make it appear after typing an array na ...

Navigating back with the back button in Vue js without refreshing the prior page

I recently developed a website with 3 pages, where the first page links to the second and the second links to the third. However, I've encountered an issue when users click the back button. Instead of navigating to the previous page with the full brow ...

Select information from an array and store it within an object

I want to extract all objects from an array and combine them into a single object. Here is the current array data: userData = [ {"key":"firstName","checked":true}, {"key":"lastName","checked":true ...

Despite declaring a default export, the code does not include one

Software decays over time. After making a small modification to a GitHub project that was three years old, the rebuild failed due to automatic security patches. I managed to fix everything except for an issue with a default import. The specific error mess ...

"The act of initializing an EntryComponent in Angular results in the creation of a brand

In my main component, app.component.ts, I have integrated a new service into the providers[] array and initialized it in the constructor: @Component({ selector: 'app-main', templateUrl: './app.component.html', styleUrls: ['. ...

Using Typescript: ForOf Iteration with Unknown Value Types

My journey began with a quick peek at this particular inquiry. However, the approach discussed there utilized custom typing. I am currently iterating over object entries using a for-of loop. Here's a snippet of the values I'm dealing with below. ...

Navigating TS errors when dealing with child components in Vue and Typescript

Recently, I encountered an issue where I created a custom class-based Vue component and wanted to access its methods and computed properties from a parent component. I found an example in the Vue Docs that seemed to address my problem (https://v2.vuejs.org ...

What measures can I take to ensure TypeScript transpiles prototype methods effectively?

Having some issues defining methods on a TypeScript class and then accessing them. Even though the methods are defined, it's giving an error that they don't exist. TypeScript: export class ColumnHeader extends JSONObject { // ... i ...

What is the significance of using a double arrow function in Javascript?

Can someone explain the double arrow notation used in the code snippet below? How does the second arrow function get executed if the first one's response is true? And in what scenarios is this notation typically used? async check({ commit }) { ...

What is the proper way to integrate helmet.js with typescript?

Utilizing helmet from pure JavaScript according to the documentation is quite straightforward: const express = require('express') const helmet = require('helmet') const app = express() app.use(helmet()) However, I'm unsure how ...

Capture data from a Telegram bot and store it in a Google Sheet

I am trying to use a spreadsheet through a Telegram bot as a TODO list so that when I input something on my phone, it is saved in the spreadsheet. (I'm following this tutorial https://www.youtube.com/watch?v=XoTpdxbkGGk, which seems accurate with Goog ...