Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue & Typescript: How to avoid TS error when accessing child component's methods

I've created a custom class-based vue component and I'm trying to access its methods and/or computed properties from a parent component. There is an example in the Vue Docs that explains what I'm trying to do (https://v2.vuejs.org/v2/guide/components-edge-cases.html#Accessing-Child-Component-Instances-amp-Child-Elements). So basically it's this

class ParentComponent extends Vue {
    someMethod() {
        (this.$refs.myChildRef as ChildComponent).focus()
    }
}

class ChildComponent extends Vue {
    focus() {
        // do something
    }
}

Now, this leads to a TS error: "TS2339: Property 'focus' does not exist on type 'Vue'"

So apparently, typescript doesn't see that my ChildComponent has additional methods.

The code still works during runtime though, so it just appears to be a typescript issue.

Does anyone have an idea how to solve this?

like image 772
overdub60 Avatar asked Aug 08 '19 16:08

overdub60


People also ask

What is Vue used for?

Vue. js is a progressive framework for JavaScript used to build web interfaces and one-page applications. Not just for web interfaces, Vue. js is also used both for desktop and mobile app development with Electron framework.

Does Vue have a Michelin star?

Vue – Singapore - a MICHELIN Guide Restaurant.

Is VueJS a programming language?

Note that Vue is both a programming and a script language: it is a dedicated dynamic tracing language. Vue supports a subset of C and scripting syntax that is most beneficial for dynamic tracing purposes.

Why should I use Vue?

Vue is lightweight, easy to learn, pleasant to write in, and not difficult to integrate with legacy technologies or an application without a specified framework. Because of its familiar templating syntax and use of components, integrating or migrating existing projects to Vue is faster and smoother.

What is Vue?

What is Vue? Vue (pronounced /vjuː/, like view) is a JavaScript framework for building user interfaces. It builds on top of standard HTML, CSS and JavaScript, and provides a declarative and component-based programming model that helps you efficiently develop user interfaces, be it simple or complex.

What are the built-in Vue directives?

Vue.js directives offers functionality to HTML applications Vue.js provides built-in directives and user defined directives Vue.js uses double braces { { }} as place-holders for data. In the example below, a new Vue object is created with new Vue (). The property el: binds the new Vue object to the HTML element with id="app".

How do I get support for Vue JS?

Supporting Vue.js. Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider: Become a backer or sponsor on Patreon. Become a backer or sponsor on Open Collective.

Why should I donate to Vue?

Your name/logo will receive proper recognition and exposure by donating on either platform. Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. It is designed from the ground up to be incrementally adoptable, and can easily scale between a library and a framework depending on different use cases.


3 Answers

Option 1: Ignore it

//@ts-ignore

Option 2: Type any

const child: any = this.$refs.myChildRef;
child.focus();

Option 3: Interface, as mentioned by @LLai

interface ComponentInterface {
    focus: () => void
}

Option 4: Merge types

As a one liner as @LaLai says

(this.$refs.myChildRef as ChildComponent & { focus: () => void }).focus()

or if you need it more often

Class ParentComponent extends Vue {
    $refs: Vue["$refs"] & {
      myChildRef: { focus: () => void }
    };  
}

Option 5: @Ref() decorator from vue-property-decorator

Class ParentComponent extends Vue {
  @Ref()
  childComponent: ChildComponent
}
like image 67
Reynicke Avatar answered Oct 19 '22 20:10

Reynicke


One solution is to implement an interface on your child component.

interface ComponentInterface {
    focus: () => void
}

class ChildComponent extends Vue implements ComponentInterface {
    focus () {
        // do something
    }
}

Another option is to merge the types

class ParentComponent extends Vue {
    someMethod() {
        (this.$refs.myChildRef as ChildComponent & { focus: () => void }).focus()
    }
}

But this can get repetitive if you are calling focus a lot outside of the child component. I prefer option 1.

like image 29
LLai Avatar answered Oct 19 '22 20:10

LLai


We have similar issues with our components which were built using typescript. The solution we are using for now, is just adding a ts-ignore comment before each of issue. It's not the best way but it works.

//@ts-ignore

try it out

like image 40
carlosza Avatar answered Oct 19 '22 20:10

carlosza