Oteto Blogのロゴ

【TypeScript】Event.targetに型を付けてvalueを参照する

困ったこと

const handleInput = (event: InputEvent) => {
  console.log(event.target.value);
  // => Property 'value' does not exist on type 'EventTarget'.
};

TypeScriptでInputEventを扱う際などに、event.targetevent.currentTarget)のvalueを参照しようとすると上記のエラーになる。

原因はevent.targetが何のElementに該当するかはコンパイラーが推論できておらず、単純にEventTargetと推論されているため。

解決法

1. targetに型指定しつつ直接取り出す

const handleInput = (event: InputEvent) => {
const handleInput = ({ target }: { target: HTMLInputElement }) => {
  console.log(target.value);
};

targetのみを参照する場合に限る。

2. instanceofで型ガードする

const handleInput = (event: InputEvent) => {
  if (!(event.target instanceof HTMLInputElement)) throw new TypeError();
  console.log(event.target.value);
};

3. Event型を拡張する

interface HTMLElementEvent<T extends EventTarget> extends Event {
  target: T;
}

const handleInput = (event: InputEvent) => {
const handleInput = (event: HTMLElementEvent<HTMLInputElement>) => {
  console.log(event.target.value);
};

Eventを継承した型を作成し、targetをジェネリクスで受け取った型に上書きする。

4. asで型アサーションする

const handleInput = (event: InputEvent) => {
  console.log(event.target.value);
  console.log((event.target as HTMLInputElement).value);
};

これは最終手段。

Reactの場合

import type { ChangeEvent } from "react";

const handleInput = (event: InputEvent) => {
const handleInput = (event: ChangeEvent<HTMLInputElement>) => {
  console.log(event.target.value);
};

React.ChangeEventのジェネリクスに対象のElementを指定する。