Vue Composition API - getting a ref using TypeScript

Viewed 12384

Vetur is underlining null on this line below:

const firstRef = ref<HTMLElement>(null)
No overload matches this call.
 Overload 1 of 3, '(raw: HTMLElement): Ref', gave the following error.
  Argument of type 'null' is not assignable to parameter of type 'HTMLElement'.
 Overload 2 of 3, '(raw: HTMLElement): Ref', gave the following error.
  Argument of type 'null' is not assignable to parameter of type 'HTMLElement'.Vetur(2769)

Here's a condensed context. Any ideas what I did wrong?

<template>
  <input id="first" ref="firstRef">
  <button type="button" @click.prevent="focusFirst">Focus</button>
</template>

<script lang="ts">
import { defineComponent, ref } from "@vue/composition-api"
export default defineComponent({
  name: "Test",
  setup() {
    const firstRef = ref<HTMLElement>(null)
    const focusFirst = () => {
      const theField = firstRef.value
      theField.focus()
    }

    return { focusFirst }
  }
</script>
3 Answers

As given back by Vetur, you cannot convert a null type to an HTMLELement type. A possible way to fix this would be to write:

const firstRef = ref<HTMLElement | null>(null)

However, keep in mind that you'll have to check if firstRef is of type null every time you want to use it. You could do something like this as well:

if (firstRef.value) {
  // do stuff with firstRef
  // typescript knows that it must be of type HTMLElement here.
}

Another approach might be optional chaining (since TS 3.7):

firstRef.value?.focus()

This will be fine for TS and execute the command only if firstRef.value is not null or undefined.

const firstRef = ref<HTMLElement | null>(null)

will cause error when you try to access not only HTML props also vue component methods & props. So it will be better to use:

const myComponentRef = ref<InstanceType<typeof MyComponent>>()

Referance: Typing of component refs

Related