How to define type for ref(binding on template) In Vue3, using TypeScript?

20,652

Solution 1

Well, that would depend on whether or not you need it typed and to provide member information (public properties, methods, etc). If you do, then yes you need to define a type for it; otherwise, you don't have to, and can simply access the unwrapped reference with .value which leaves it as type any (I bet you figured out this one).

But if you have to, you need to tell the compiler what it is or what it's going to be assigned on. To do that, you'll want to use the third overload of ref (with no argument) and explicitly set the generic type to the desired type—in your case, you want HTMLDivElement (or simply HTMLElement if you don't care about the specific members it has to offer).

export default defineComponent({
  setup() {
    const el = ref<HTMLDivElement>();

    onMounted(() => {
      el.value // DIV element
    });

    return {
      el
    }
  }
})

In JavaScript, you don't have type checking, so passing null on the ref function is as good as not passing anything (which is especially okay for template refs)*; it could even come across as being misleading in a sense that the unwrapped value actually resolves to something else but null.

* When using the Composition API, the concept of "reactive refs" and "template refs" are unified. And the reason we're accessing this particular type of ref on the mounted hook is because the DOM element will be assigned to it after initial render.

References:

Solution 2

The line isn't correct:

    const el = ref<HTMLDivElement>();

The el is not an HTMLDivElement. Instead, it's a proxy to the element. The $el of that proxy is the actual HTMLDivElement. Though I'm not sure if I get it right. In a component, I managed to type it as follow:

import { ComponentPublicInstance, defineComponent, ref } from 'vue';

export default defineComponent({
  // snipped...
  setup() {
    const field = ref<ComponentPublicInstance<HTMLInputElement>>();
    return {
      field,
      fun() { field.value.$el.value = 'some value'; }
    };
  }
  // snipped...
});
Share:
20,652
Shook Lyngs
Author by

Shook Lyngs

Updated on July 09, 2022

Comments

  • Shook Lyngs
    Shook Lyngs almost 2 years

    Template:

    <tremplate>
      <div ref="element"></div>
    </template>
    

    Script:

    export default {
      setup() {
        const element = ref(null);
        return {
          element,
        };
      },
    };
    

    This is a normal way to define a ref in vue3, but in JavaScript way. And if I'm using TypeScript, I will need to define a type for value element, right?

    How do I do to ensure the correct type for value element?

  • Michael2
    Michael2 about 3 years
    This is wrong for normal div Elements. For <div ref="test">, use: ref<HTMLDivElement> For <my-app-component ref="test">, use ref<PublicComponentInstance<MyAppComponent>>
  • Michael2
    Michael2 about 3 years
    Mind that it is not null, but undefined. So your type of el in this case would be: Ref<HTMLDivElement | undefined> Passing null to a function is not the same as just leaving out that parameter (in which case it is undefinded)
  • coyotte508
    coyotte508 almost 3 years
    Any idea on how to achieve this when the referenced item is a vue component, not a native DOM element? Is there a way to get the ThisType of the referenced component?
  • Yom T.
    Yom T. almost 3 years
    @coyotte508 Does this answer your question?
  • coyotte508
    coyotte508 almost 3 years
    @YomT. it does!