-
Notifications
You must be signed in to change notification settings - Fork 342
Description
TL;DR: I'm using TypeSript. I want to call methods on a sub-component via it's ref from inside a hook (like onMounted, onBeforeUnmount, etc.). In order to do that I need to know which type to assign to the template ref. By default it's a VueProxy<>
, wich doesn't help me.
Long version:
When I include sub-components in my component template I want to access them in a typesafe manner, specifically in order to call a method on the sub-component.
I know that the "official" way is to only communicate through props and events and that works fine. However, there are some use cases where the best way is to simply call a method on a sub component.
In my case, I have an editor wrapped in a sub-component. This editor is pretty complex and has it's own internal document model. The parent component is only interested in the serialized JSON string of the document in order to save it together with some metadata that's coming from other components. It should not have to care about the internal model of the editor. Since serializing the document is potentially expensive, I have debounced the input event on the editor so that the document is serialized and sent to the parent via a custom event once the user stops typing for a bit. However, that raises the potential for data loss should the user accidentally navigate away from the page before the debounced event is sent. So I want to create a hook that flushes the debounced events in the child components, like this:
<template>
<div>
<my-editor ref="myEditor" @input="save"/>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue-composition-api";
import MyEditor from "@/components/myeditor.vue";
export default defineComponent({
setup() {
const myEditor = ref<typeof MyEditor>(); // this is assigned correctly on mounting
onBeforeUnmount(() => {
if (myEditor.value) {
myEditor.value.flushEvents(); // this gives an error "Property 'flushEvents' does not exist on Type VueProxy<{...}>
}
});
return { myEditor };
}
});
</script>
So the main issue is the typing here. This all works great when the template ref is a normal HTMLElement. I can call all methods and access all properties in a typesafe way. Unfortunately I don't know what type to assign to the ref for a component. VueProxy doesn't seem to help much.
This works great for props. They are automatically typed correctly. It would be awesome to have this for refs as well.
I have this same problem in my navigation guards by the way, but that is likely a different issue.
Also: I know there are ways around this. If I just don't assign a type to the ref everything will work fine, but TypeScript will complain all the time, which breaks some build processes and dilutes the actually usefull errors.