DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 967,911 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for πŸ€·β€β™‚οΈ πŸ€·β€β™€οΈ Vue 3 error with using TypeScript: property X does not exist on type 'EventTarget'
Vic ShΓ³stak
Vic ShΓ³stak

Posted on • Updated on

πŸ€·β€β™‚οΈ πŸ€·β€β™€οΈ Vue 3 error with using TypeScript: property X does not exist on type 'EventTarget'

Introduction

Hey, DEV people! πŸ‘‹ It's time to continue the Simple Errors series with an article about the TypeScript error I encountered when I first decided to convert my Vue.js v3.x project from regular JavaScript.

As always, don't judge too harshly, write what you think of such articles, suggest your own topics for parsing in the comments... Here we go! πŸš€

πŸ“ Table of contents

Explanation of the error

When I run vue-tsc --noEmit to check TypeScript, I get errors:

src/components/forms/Input.vue:4:40 - error TS2531: 
Object is possibly 'null'.

4     @input="$emit('update:modelValue', $event.target.value)"
                                         ~~~~~~~~~~~~~

src/components/forms/Input.vue:4:54 - error TS2339: 
Property 'value' does not exist on type 'EventTarget'.

4     @input="$emit('update:modelValue', $event.target.value)"
                                                       ~~~~~

Found 2 errors.
Enter fullscreen mode Exit fullscreen mode

While I knew what was wrong with error Object is possibly 'null', I had to dig deep into the documentation to find the reason for error Property 'value' does not exist on type 'EventTarget'.

↑ Table of contents

Input data when an error occurs

My Vue component (src/components/forms/Input.vue) looks like this:

<template>
  <input
    class="px-3 py-2 border-2 rounded-lg"
    @input="$emit('update:modelValue', $event.target.value)"
    :type="inputType"
    :tabindex="tabIndex"
    :placeholder="placeholder"
    :value="modelValue"
    :required="isRequired"
  />
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'Input',
  props: {
    inputType: { type: String, required: true },
    tabIndex: { type: String, required: true },
    placeholder: { type: String, default: '' },
    modelValue: { type: String, default: '' },
    isRequired: { type: Boolean, default: false },
  },
})
</script>
Enter fullscreen mode Exit fullscreen mode

As you've already noticed, in the @input attribute of the template, I refer to $event.target.value as I would do in regular JavaScript.

πŸ€” Note: Even if $event.target return null, which has no value property, this is not a big problem for regular JavaScript! It will give a run-time error on the client and this web application will crash.

But that's not how TypeScript works. It checks all possible problematic places in the code at the time of building the project and points them out.

That's why we love and use it!

↑ Table of contents

solve the problem

Resolving the error

First, write a new method called handleInputChange(event) in setup function:

// ...

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  // ...
  setup: () => {
    // Define event handler for input changes in TypeScript.
    const handleInputChange = (event: Event) => 
      (event.target as HTMLInputElement).value

    return { handleInputChange }
  },
})
</script>
Enter fullscreen mode Exit fullscreen mode

In TypeScript, we need to explicitly point to the object we want to work with. In this case, it is the input field, so its object will be called HTMLInputElement.

☝️ Note: The HTMLInputElement interface provides special properties and methods for manipulating the options, layout, and presentation of <input> elements.

Next, let's add this method to the @input in our template, like this:

<template>
  <input
    class="px-3 py-2 border-2 rounded-lg"
    @input="$emit('update:modelValue', handleInputChange($event))"
    :type="inputType"
    :tabindex="tabIndex"
    :placeholder="placeholder"
    :value="modelValue"
    :required="isRequired"
  />
</template>

// ...
Enter fullscreen mode Exit fullscreen mode

Run vue-tsc once again... and boom! πŸ’₯ All errors disappeared.

↑ Table of contents

Conclusions

I know how difficult it is to retrain to a new paradigm of interaction with the same objects and properties! But this simple error showed me just how powerful and useful TypeScript is in the real world.

Have a successful work and let simple errors never stop you on the way to realizing your projects! πŸ˜‰

↑ Table of contents

Photos and videos by

P.S.

If you want more articles like this on this blog, then post a comment below and subscribe to me. Thanks! 😘

And, of course, you can support me by donating at LiberaPay. Each donation will be used to write new articles and develop non-profit open-source projects for the community.

Support author at LiberaPay

Top comments (2)

Collapse
 
hydracorey profile image
Corey Vincent

Thank you this was super helpful. I was trying to pass in the checked value for a checkbox, this solved the error for me.

<input
  type="checkbox
  @change="changeSomething($event)"
  >
Enter fullscreen mode Exit fullscreen mode
function changeSomething(event: Event) {
  const checkBox = (event.target as HTMLInputElement)
  if (checkBox.checked){
    ...
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
evenhuis81 profile image
Evenhuis81

I was trying to figure out how to do this with JSDoc (standard JS Typescript for VS Code) and within the inline property of @change on the component. (so without the need of an extra function), this is what eventually worked:

@change="event => (modelValue = /**@type {HTMLInputElement} */ (event.target).value)"

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.