🤷‍♂️ 🤷‍♀️ Vue 3 error with using TypeScript: property X does not exist on type 'EventTarget'
Tags: vue, typescript, showdev, beginners
Published: 2021-09-06 07:45:45

## 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](https://v3.vuejs.org/guide/introduction.html) `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! 🚀

<a name="toc"></a>
### 📝 Table of contents

- [Explanation of the error](#explanation-of-the-error)
- [Input data when an error occurs](#input-data-when-an-error-occurs)
- [Resolving the error](#resolving-the-error)
- [Conclusions](#conclusions)

<a name="#explanation-of-the-error"></a>
## Explanation of the error 

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

```console
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.
```

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](#toc)

<a name="#input-data-when-an-error-occurs"></a>
## Input data when an error occurs

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

```vue
<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>
```

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](#toc)

![solve the problem](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z11642wyh1kar7n8vtfy.jpg)

<a name="#resolving-the-error"></a>
## Resolving the error

First, write a new method called `handleInputChange(event)` in [setup](https://v3.vuejs.org/guide/composition-api-setup.html) function:

```vue
// ...

<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>
```

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](https://developer.mozilla.org/en-US/docs/Web/API/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:

```vue
<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>

// ...
```

Run `vue-tsc` once again... and boom! 💥 All errors disappeared.

[↑ Table of contents](#toc)

<a name="#conclusions"></a>
## 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](https://www.typescriptlang.org/) 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](#toc)

<a name=""></a>
## Photos and videos by

- Sascha Bosshard https://unsplash.com/photos/qhhp1LwvPSI
- Lucrezia Carnelos https://unsplash.com/photos/yGv-pvgRuiI

<a name=""></a>
## 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 help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv