타입스크립트와 EventTarget💗
타입스크립트와 EventTarget
타입스크립트를 사용하면서 이벤트 타깃을 사용하면 종종 에러를 마주하곤 한다.
빠르게 그 이유를 말하자면, EventTarget은 Element type으로부터 상속받지 않기 때문에 에러를 만나게 되는 것이다. 그렇기에 id 혹은 class와 같은 속성을 인지하지 못하는 것이다. 즉, 이벤트 타깃은 EventTarget의 타입이 있다.
그럼 왜 Element type에서 상속받지 않는 것일까? 나도 이 생각을 가장 많이 했다. 결론적으로 우리가 이벤트를 실행시킬 때 가장 많이 하는 일은 앨리먼트에 이벤트를 붙이기 때문이다!
하지만 우리가 알아야 할 것은 모든 이벤트 타깃이 HTML elements에 한정되지 않는 다는 것이다
예를 들면, XMLHttpRequest, FileReader, AudioNode, AudioContext 등..
✨ 해결방법1 : Target의 타입을 지정해준다.
const menuBtn = document.querySelector('.menu_btn');
menuBtn.addEventListener('click', function (e) {
const target = e.target as Element; // 1️⃣
(e.target as Element).className; // 2️⃣
}, false);
// 3️⃣
menuBtn.addEventListener('click', function (e: { target: Element }) {
console.log(e.target.className); // 'foo'
}, false);- e.target이 Element라는 것을 알려준다.
- inline으로 사용한다.
- 만약에 이벤트의 target 속성만 사용할 경우 이렇게 적어준다.
당연한 말이지만 이벤트의 타입을 지정한 것이 아니기 때문에 e.type과 같은 타깃 외에 다른 속성을 사용하면 오류가 발생한다.
✨ 해결방법2 : Event의 타입을 지정해준다.
이벤트 자체에 타입을 지정해주면 target이외에 다른 속성도 사용할 수 있다. 물론 타깃은 Element외에 다른 타깃도 받아올 수 있기 때문에 함께 지정해주어야 한다!
const menuBtn = document.querySelector('.menu_btn');
menuBtn.addEventListener(
'click',
function (e: Event & { target: Element }) {
console.log(e.target.className); // 'menu_btn'
console.log(e.type); // 'click'
},
false,
);✨ 해결방법3 : EventTarget의 타입을 더 명확하게 지정할 수 있으면 그렇게 해야한다..
예를 들며, form event를 작성해야한다고 가정해보자. 아마 대부분의 사람들은 input의 value를 받아오는 작업을 작성하고 있을 것이다 (= 나👩💻)
그때 또 다른 에러를 마주하게 될 것이다. 🤬
💻 : "Property 'value' does not exist on type 'EventTarget'"
그때는 더 디테일하게 Target의 타입을 지정해주면 된다 😑
const input = document.getElementById('input_elem');
input.addEventListener('input', function (e) {
console.log((e.target as HTMLInputElement).value);
}, false);- EventTarget의 타입에는 없지만 HTMLInputElement 타입에는 value 속성이 있기 때문에 작동이 된다.
그 외에 자주 사용하면 타입 모음
// classList 속성 사용 시
e.target as Element
e.target as HTMLElement
e.target as HTMLImageElement
e.target as HTMLMediaElement
e.target as HTMLVideoElement
e.target as HTMLAudioElement
e.target as HTMLInputElement
e.target as HTMLTextAreaElement
// 이렇게 타입을 지정해 준 후 사용도 가능!
type InputType = HTMLInputElement | HTMLTextAreaElement
e.target as InputType