(TypeScript) Type MouseEvent is not generic. 에러 및 해결

SuKyoung·2022년 12월 11일
4

에러노트

목록 보기
4/4
post-thumbnail

TypeScript에 익숙해지기 위해, Canvas를 활용하여 그림판 만들기를 구현하고 있습니다.

Canvas Element를 클릭 시, 발생하는 마우스 프로퍼티(clientX와 clientY)를 사용하여 클라이언트 좌표를 받아오도록 구현했는데, TypeScript를 잘 모르다보니 뭐가 잘못됐는지도 모른 채 한참 삽질을 했습니다. (ㅠㅠ)

ISSUE

1️⃣ 첫번째 시도
interface를 사용하여 타입을 지정해줬는데, 타입이 맞지 않는다는 에러가 뜹니다.

interface Props { 
  clientX: number;
  clientY: number;
}

const Canvas = () => {
  const handleClick = ({
      clientX: e.clientX, 
      clientY: e.clientY
    }: Props // 🔴 No overload matches this call. ts(2769)
  ) => {
    console.log(e.clientX, e.clientY)
  };
  
  return <canvas onClick={handleClick} />;
};

export default Canvas;

2️⃣ 두번째 시도

이번에는 d.ts 파일을 참고하여, Generic 형태를 사용하여 변경해보았으나, 이번에는 마우스이벤트 타입은 Generic 형태가 아니라는 에러가 뜹니다. 오잉, 구현체에는 Generic으로 나와있지 않았나? 점점 의문에 빠집니다. 🤔

// node_modules/@types/react/index.d.ts
interface MouseEvent<T = Element, E = NativeMouseEvent> extends UIEvent<T,E> {
  altKey: boolean;
  button: number;
  clientX: number;
  clientY: number;
  // etc...
}
import { MouseEvent } from "react";

interface Props {
  clientX: number;
  clientY: number;
}

const Canvas = () => {
  const handleClick = ({
      clientX: e.clientX, 
      clientY: e.clientY
    }: MouseEvent<Props> // 🔴 Type MouseEvent is not generic.  ts(2315) 
  ) => {
    console.log(e.clientX, e.clientY)
  };

  return <canvas onClick={handleClick} />;
};

export default Canvas;

SOLUTION

d.ts에 정의된 파일을 다시 보면 MouseEvent<T = Element>이라고 나와있는데, < > 안에는 어떤 HTML Element가 들어오는지를 써달라는 의미였습니다. 즉, 올바른 타입형태는 MouseEvent<HTMLCanvasElement>를 사용해주면 됩니다. 🤪

type CanvasMouseEvent = MouseEvent<HTMLCanvasElement>; // ✅ MouseEvent<T = Element>

const Canvas = () => {
  const handleClick = (e: CanvasMouseEvent) => {
    console.log(e.clientX, e.clientY)
  };

  return <canvas onClick={handleClick} />;
};
// node_modules/@types/react/index.d.ts
interface MouseEvent<T = Element, E = NativeMouseEvent> extends UIEvent<T,E> {
  altKey: boolean;
  button: number;
  clientX: number;
  clientY: number;
  // etc...
}

더 생각해볼 문제🤔

  • 어떤 경우에 interface를 사용할 지, type을 사용할 것인지에 대한 명확한 기준을 정하는 것이 좋을 듯
  • 이 경우에는 별로 크지 않은 함수이고 타입 추론을 편리하게 할 수 있으니까 인라인 함수로 선언하는 것도 괜찮을 듯!
    <canvas onClick={(e) => console.log(e.clientX, e.clientY) /> // ✅ e에 타입 재정의 할 필요가 없음
profile
👩‍💻 Frontend Engineer | 📝 Hobby Blogger

0개의 댓글