Search code examples
typescriptvue.jstypescript-decoratorvue-class-components

Casting a component with vue typescript - accessing child methods


I am trying to access a child component method. Usually this is fine

 this.$refs.searchInput.reset()

To keep typescript happy this is required.

(this.$refs.searchInput as HTMLFormElement).reset()

I am not overly keen on the syntax. Is there no way to cast in the component options

export default Vue.extend({
  name: 'UserForm',
  components: {
       SearchInput as HTMLFORMELEMENT
    }

Should I use the class/decorator syntax for this to make this possible?


Solution

  • There's no official way to declare the type for $refs in component options.

    Indeed it seems you can avoid the type assertion by using either vue-class-component:

    import Vue from 'vue'
    import Component from 'vue-class-component'
    
    @Component
    export default class UserForm extends Vue {
      $refs!: {
        searchInput: HTMLFormElement
      }
    
      mounted() {
        this.$refs.searchInput.reset()
      }
    }
    

    or vue-property-decorator:

    import { Vue, Component, Ref } from 'vue-property-decorator'
    
    @Component
    export default class UserForm extends Vue {
      @Ref() readonly searchInput!: HTMLFormElement
    
      mounted() {
        this.searchInput.reset()
      }
    }
    

    Alternatively, you can use the Composition API, declaring the type for the template ref:

    import { defineComponent, ref, onMounted } from 'vue' // or `@vue/composition-api` for Vue 2
    
    export default defineComponent({
      setup() {
        const searchInput = ref<HTMLFormElement>()
    
        onMounted(() => searchInput.value?.reset())
    
        return { searchInput }
      }
    })
    

    demo