Reputation: 738
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?
Upvotes: 9
Views: 6967
Reputation: 1550
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
}
Upvotes: 12
Reputation: 11
I don't want to declare the method name twice so I use this way:
In ChildComponent.ts
import Vue from 'vue'
export default class ChildComponent extends Vue.extend({
methods: {
focus() {}
}
}){}
In ChildComponent.vue
<template>...</template>
<script lang="ts">
import ChildComponent from './ChildComponent'
export default ChildComponent;
</script>
In ParentComponent
import Vue from 'vue'
import ChildComponent from './ChildComponent.vue'
import ChildComponentClass from './ChildComponent'
export default class ParentComponent extends Vue.extend({
components: {ChildComponent},
methods: {
someMethod() {
(<ChildComponentsClass>this.$refs.child).focus();
}
}
}){}
Upvotes: 0
Reputation: 13406
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.
Upvotes: 2
Reputation: 375
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
Upvotes: 1