TypeScript에 익숙해지기 위해, Canvas를 활용하여 그림판 만들기를 구현하고 있습니다.
Canvas Element를 클릭 시, 발생하는 마우스 프로퍼티(clientX와 clientY)를 사용하여 클라이언트 좌표를 받아오도록 구현했는데, TypeScript를 잘 모르다보니 뭐가 잘못됐는지도 모른 채 한참 삽질을 했습니다. (ㅠㅠ)
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;
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에 타입 재정의 할 필요가 없음