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

Having issues with Vue.js v-repeat not displaying any content

I have just started learning about vue.js. I attempted to display a simple list, but it is not showing anything. Here is my code: <html> <head> <title>VUE Series</title> <link rel="stylesheet" type="text/css" ...

Issue: Unspecified error when trying to access object attribute in Vue (Nuxt)

I am facing an issue with my 'region' object. It appears to be displayed correctly with all its attributes, but when I try to access specific attributes, it shows up as 'undefined'. const region = { "id": 7, "name": ...

How can Vue listen for a Vuex commit?

Is there a method to detect when a Vuex commit occurs without having to monitor specific property changes associated with the commit? Simply knowing if a commit has taken place? I am working on a Filter component that I plan to include in an NPM package. ...

Adding a new value to a string variable using TypeScript

Just starting out with Angular and I'm looking to capture user input from a text box with each keystroke and add it to a string variable like in Java. In my text box, I have the following setup for capturing key events: <input type="text" ...

Exploring the distinction between "() => void" and "() => {}" in programming

Exploring TS types, I defined the following: type type1 = () => {} type type2 = () => void Then, I created variables using these types: const customType1: type1 = () => { } const customType2: type2 = () => { } The issue surfaced as "Type ...

Is It Possible to Save Data to Local Storage Using Vue.js?

I am currently working on storing data using Vue.js and local storage. By writing localStorage.set('something', 5) in my main.js file, I can view the data in the Chrome dev tools under the 'Storage' section in the 'Application&apo ...

How to bring in a class that was exported using `export = uuid` in Typescript

I'm facing a challenge while working with the node_module called uuid-js in TypeScript. After installing both the module and its typings, I am unsure how to properly import the module. Question: What is the correct way to import the module? The func ...

Using Vue with Firebase to fetch a specific range of data starting from a particular record and ending at the

I am looking to retrieve all records from a certain record to the very last one in my database. ref.orderByChild("date").equalTo("19/11/2020 @ 19:50:29").on("child_added", (snapshot) => { console.log(snapshot.va ...

Change object values to capital letters

Upon retrieving myObject with JSON.stringify, I am now looking to convert all the values (excluding keys) to uppercase. In TypeScript, what would be the best way to accomplish this? myObj = { "name":"John", "age":30, "cars": [ { "name":"Ford", ...

Intercepting Nested Requests in a Nest.js Application

Can you explain how to incorporate a nested interceptor in Nest.js? I currently have two interceptors: UsersInterceptor and PostsInterceptor UsersInterceptor: @Injectable() export class UsersInterceptor<T> implements NestInterceptor<T, Response& ...

How to create a clickable link using Vuetify's v-btn component

As a newcomer to vue and vuetify, I would greatly appreciate some explanation and examples. My goal is to create a button that directs users to an external site, like youtube.com. Below is the code I currently have, but unfortunately it's not function ...

Vue3 - Quasar q-tabs do not maintain values between them

I am facing an issue while designing a screen to submit a form in modal using vue3 and quasar. I have organized the form components by tabulating them, but when I switch tabs, the current selection disappears, showing the old value when I return. However, ...

Angular: Granting an external module access to a provider

One of the modules I imported provides a service with an optional dependency. Although it being optional didn't affect my application, as it just prevented any errors from occurring when not present. Here's an example: import { FooModule } from ...

Set the subscription's value to the class property without changing its original state

Lately, I have been using the following method to set the value of a subscription to a property in my classes: export class ExampleComponent implements OnInit { exampleId: string; constructor(public route: ActivatedRoute) { this.route.params.subs ...

What is the method for integrating my SVG icons with q-btn-toggle?

I'm currently integrating SVG icons into my project using Quasar and I am facing an issue with the q-btn-toggle component. The documentation suggests providing a direct path to the SVG file, but in reality, the icon does not display. Below is a snippe ...

Selecting the appropriate v-model for Vue.js draggable in the case of a nested list

My Vue Component <div id="main"> <h1>Vue Dragable For</h1> <div class="drag"> <ul> <li v-for="category in data"> <draggable id="category" v-model="category" :move="checkMo ...

Angular - Ensuring service completion before proceeding with navigation

I'm currently facing an issue where I need to populate data in a service before navigating, but the navigation is happening before the data is ready. Here's the code in my service: addToken(token) { this.cookieService.set( 'token', ...

Inconsistency with Angular 4 instance variables causes ambiguity within a function

Here is the code snippet: @Component({ selector: 'unb-navbar', templateUrl: './navbar.html' }) export class NavbarComponent implements OnInit { @Input() brand: string; controlador:boolean=false; overlay:string=""; @Input() menu ...

Issue with Angular ngStyle toggle functionality not activating

I'm having an issue with toggling my navbar visibility on click of an image. It works the first time but not after that. Can anyone provide some assistance? Link to Code <img id="project-avatar" (click)="toggleNavbar()" width=20, height=20 style= ...

Looping through various object attributes and accessing an array of objects within it

Within my application, I am currently receiving an object structured as follows: { "data1":[ {},{}{} ], "data2":[ {},{},{}....], "data3":[ {},{},{}.....] } I am looking for guidance on how to utilize v-f ...