13

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 3

20

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.
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks. This worked but I had to use firstRef.value. If you update you answer, I'll mark it as correct.
I'm just getting started, so I'm not sure about the pros / cons, but it seems like you could use const firstRef = ref<HTMLElement>(), which would just make the ref HTMLElement | undefined, but it's a little shorter. Technically, you could also override the type system with something like ref<HTMLElement>(null!), but that might be a bad idea since it can lead to unsafe usage before the ref is initialized (e.g. before the component is mounted).
It would work as well @jon_wu, however undefined means something different than null in javascript. I think null, by its definition, is better suited for this use case. Because undefined would imply that firstRef.value does not exist.
@Keimeno Totally agree null feels more correct and pure. Was just thinking that for some, they might prefer the brevity and potential readability of the more concise option. In practice, between null | undefined | HTMLElement, you may often just care about whether something is truthy, e.g. if (firstRef.value).
With HTMLElement type, to access component methods is not allowed. Because component methods are not in the HTMLElement type
|
2
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

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.