Creating Child Components in Vue Using Typescript

After using Vue for some time, I decided to transition to implementing Typescript. However, I've encountered an issue where accessing the child's methods through the parent's refs is causing problems.

Parent Code:

<template>
  <ref-test ref="child"/>
</template>

<script lang="ts">
import Vue from "vue";
import RefTest from "./RefTest.vue";

export default Vue.extend({
  name: "RefParent",
  components: {
    RefTest
  },
  data: () => ({}),
  methods: {},
  mounted() {
    const child = this.$refs.child as RefTest;
    child.pingMe();
  }
});
</script>

<style scoped></style>

Child Code:

<template>
  <div>REF TEST...</div>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
  name: "RefTest",
  data: () => ({}),
  methods: {
    pingMe() {
      console.log("refTest pingMe");
    }
  }
});
</script>

<style scoped></style>

The challenge I'm facing is that when referencing the child in the parent component with

const child = this.$refs.child as RefTest;
, I encounter the error message:
'RefTest' refers to a value, but is being used as a type here.
. Additionally, child.pingMe(); results in:
Property 'pingMe' does not exist on type 'Vue'.

I've attempted various solutions mentioned in discussions like this one: https://github.com/vuejs/vue/issues/8406, particularly focusing on interface definitions and the Vue.extend<> call.

Your assistance in clarifying the distinctions in utilizing Typescript would be greatly appreciated.

Answer №1

After conducting more experiments, I have come up with a working solution that may not be considered the most elegant but gets the job done without any compiler errors. Essentially, I defined an interface type that includes the necessary method. In the parent component, I cast the $ref as this interface type and everything seems to function correctly. If there is a better or more graceful way to achieve this, please do let me know. Below is the full code snippet for reference.

Declaration of Interface (types/refInterface.ts):

import Vue from "vue";

export interface RefInterface extends Vue {
  pingMe(): void;
}

Parent Component:

<template>
  <ref-test ref="child" />
</template>

<script lang="ts">
import Vue from "vue";
import RefTest from "./RefTest.vue";
import { RefInterface } from "@/types/refInterface";

export default Vue.extend({
  name: "RefParent",
  components: {
    RefTest
  },
  data: () => ({}),
  methods: {},
  mounted() {
    const child = this.$refs.child as RefInterface;
    child.pingMe();
  }
});
</script>

<style scoped></style>

The code within the 'child' component remains unchanged in order for this implementation to work effectively.

Answer №3

Although this question may be old, I stumbled upon it and felt compelled to share my solution for those who prefer not to create an interface every time they call a single method on a reference:

mounted() {
  const child = this.$refs.child as Vue & { pingMe: () => void };
  child.pingMe();
}

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

Next.js allows for the wrapping of a server component within a client component, seamlessly

I am currently working on a project where I have implemented a form to add data to a JSON using GraphQL and Apollo Client. The project is built with TypeScript and Next.js/React. However, I am facing a conflicting error regarding server client components ...

Ways to duplicate package.json within a Dockerfile

My issue revolves around the challenge I am facing while attempting to copy my package.json to the Dockerfile context. Below is a representation of my file structure: src - apps -- api --- Dockerfile - docker -- tcp --- docker-compose.yml - package.json H ...

Utilize a Vue.js filter on the v-model within an input element

Seeking assistance! I successfully created a directive that wraps the Jasny Bootstrap Plugin, specifically focusing on the input mask feature! Additionally, I have developed a custom filter using moment to format date fields! The date format received fro ...

Next.js Issue: Invariant error - page not correctly generated

I encountered a recurring error while attempting to build my project. Strangely, everything runs smoothly during development, but as soon as the build process is initiated, the following error presents itself: next build ▲ Next.js 14.1.0 - Environm ...

Obtain the total number of requests submitted by the user within a 24-hour period

I have a POST request point in my API where I need to track and store all work journals made by a worker. export const registerPoint = async (req: Request, res: Response) => { const user = res.locals.decoded; const {id} = user; const point = new Point ...

Utilizing Dual Destructuring for Handling Undefined Main Objects

Before we proceed, I want to clarify that my question is not a duplicate of ES6 double destructure Let's examine the code snippet related to Apollo Client GraphQL: import { gql, useQuery, useMutation } from '@apollo/client'; ... const { loa ...

Vue Page fails to scroll down upon loading

I am facing a challenge with getting the page to automatically scroll down to the latest message upon loading. The function works perfectly when a new message is sent, as it scrolls down to the latest message instantly after sending. I've experimented ...

create a custom function to trigger when a new item is added to a Vuejs data property

Currently, I have a Vuejs application that is relatively simple as I am still in the learning process of Vuejs. My goal is to trigger another function whenever I add or delete from a specific data property. Here is an example code snippet: data: { prici ...

Ionic - Deleting an item from local storage

Currently, I am implementing local storage for my Ionic application. While I can successfully add and retrieve data from local storage, I encounter an issue when trying to delete a specific object - it ends up removing everything in the database. Moreover, ...

Modifying the name of a key in ng-multiselect-dropdown

this is the example data I am working with id: 5 isAchievementEnabled: false isTargetFormEnabled: true name: "NFSM - Pulse" odiyaName: "Pulse or" when using ng-multiselect-dropdown, it currently displays the "name" key. However, I want ...

Error: Unable to locate font in the VueJS build

Within my config/index.js file, I have the following setup: ... build: { index: path.resolve(__dirname, 'dist/client.html'), assetsRoot: path.resolve(__dirname, 'dist'), assetsSubDirectory: 'static', assetsPub ...

Error encountered during installation of Vuetify in Nuxt: "npm err! [email protected] install: `node build.js || nodejs build.js`"

After creating a Nuxt app using npx create-nuxt-app when running the dev server with npm run dev, I encountered the following error: ╭─────────────────────────────────────── ...

Vue.js - issue with filtering results not displaying correctly

I am currently working on an app that displays items from an external JSON file and I'm looking to implement a search input feature for filtering. Initially, the app was displaying items properly. However, once I added the filter function, it stopped ...

Adjusting the tab order dynamically within a navigation menu

I am currently facing an issue where the focus is not being ignored when the drawer is closed. Even with the showDrawer reference set to false, I can still tab through links in the closed drawer. Setting tabindex="-1" on the <nav> element does not pr ...

Using Typescript to override an abstract method that has a void return type

abstract class Base{ abstract sayHello(): void; } class Child extends Base{ sayHello() { return 123; } } The Abstract method in this code snippet has a return type of void, but the implementation in the Child class returns a number. S ...

how to adjust the width of a window in React components

When attempting to adjust a number based on the window width in React, I encountered an issue where the width is only being set according to the first IF statement. Could there be something wrong with my code? Take a look below: const hasWindow = typeof ...

Angular Typescript subscription value is null even though the template still receives the data

As a newcomer to Angular and Typescript, I've encountered a peculiar issue. When trying to populate a mat-table with values retrieved from a backend API, the data appears empty in my component but suddenly shows up when rendering the template. Here&a ...

Searching for two variables in an API using TypeScript pipes

I'm stuck and can't seem to figure out how to pass 2 variables using the approach I have, which involves some rxjs. The issue lies with my search functionality for a navigation app where users input 'from' and 'to' locations i ...

Can Angular reactive forms be used to validate based on external conditions?

Currently, I am exploring Angular reactive forms validation and facing an issue with implementing Google autocomplete in an input field: <input autocorrect="off" autocapitalize="off" spellcheck="off" type="text" class="input-auto input" formControlName ...

The variable "vue" is not properly defined within the instance, yet it is being called

I'm currently working on a Vue app and encountering an issue. The onScroll function is working correctly, but when I click the button component to trigger the sayHello function, I receive an error message. The error states: "Property or method &apo ...