[TypeScript] DOM 조작 시 타입 에러 해결하기
포스트
취소

[TypeScript] DOM 조작 시 타입 에러 해결하기

🧐 JavaScript에서는 되는데 TypeScript에서는 왜 에러가 날까요?

JavaScript에서는 DOM 요소를 선택한 뒤 바로 스타일을 바꾸는 코드를 자주 작성합니다. 그런데 TypeScript에서는 같은 코드에 빨간 줄이 생길 때가 있습니다.

대표적인 예가 querySelectorAll로 요소를 선택한 뒤 style에 접근하는 경우입니다.

1
2
3
4
const input = document.querySelectorAll(".input");

input.style.color = "red";
// Property 'style' does not exist on type 'NodeListOf<Element>'.

이번 글에서는 이 에러가 왜 발생하는지, 그리고 DOM 요소 타입을 어떻게 지정하면 되는지 정리해보겠습니다.


⚠️ querySelectorAll은 배열처럼 보이지만 NodeList입니다

querySelectorAll은 여러 요소를 가져오기 때문에 배열처럼 보이는 값을 반환합니다.

1
const inputs = document.querySelectorAll(".input");

하지만 이 값은 정확히는 NodeListOf<Element>입니다. 그래서 바로 inputs.style처럼 접근할 수 없습니다. 여러 요소 목록 자체에는 style 속성이 없기 때문입니다.

먼저 개별 요소에 접근해야 합니다.

1
2
3
const inputs = document.querySelectorAll(".input");

inputs[0].style.color = "red";

그런데 이 코드도 TypeScript에서는 에러가 날 수 있습니다.

Property 'style' does not exist on type 'Element'.

💡 Element에는 style이 없을 수 있어요

TypeScript 입장에서 Element는 아주 넓은 타입입니다.

HTML 요소일 수도 있고, SVG 요소일 수도 있습니다. 그래서 Element 타입에는 style, value, checked 같은 HTML 전용 속성이 안전하게 있다고 보장할 수 없습니다.

그래서 TypeScript에게 “이 요소는 HTML 요소야”라고 알려줘야 합니다.


🛠️ HTMLElement로 타입 지정하기

단순히 style 속성만 사용하고 싶다면 HTMLElement를 사용할 수 있습니다.

1
2
3
const inputs = document.querySelectorAll<HTMLElement>(".input");

inputs[0].style.color = "red";

querySelectorAll<HTMLElement>처럼 제네릭을 사용하면 선택된 요소의 타입을 지정할 수 있습니다.


🧩 태그별 전용 타입 사용하기

input 태그처럼 특정 태그에만 있는 속성을 사용해야 한다면 더 구체적인 타입을 지정하는 것이 좋습니다.

1
2
3
4
const inputs = document.querySelectorAll<HTMLInputElement>(".input");

inputs[0].value = "hello";
inputs[0].focus();

자주 사용하는 DOM 타입은 다음과 같습니다.

태그타입자주 쓰는 속성
inputHTMLInputElementvalue, checked, focus()
aHTMLAnchorElementhref, target
buttonHTMLButtonElementdisabled, type
imgHTMLImageElementsrc, alt
divHTMLDivElementstyle, dataset

✅ null도 함께 처리하기

querySelector는 요소를 찾지 못하면 null을 반환합니다.

1
2
3
const link = document.querySelector<HTMLAnchorElement>(".link");

link.href = "https://google.com";

위 코드는 linknull일 수 있어서 에러가 납니다. 조건문으로 확인한 뒤 사용하는 것이 안전합니다.

1
2
3
4
5
const link = document.querySelector<HTMLAnchorElement>(".link");

if (link) {
  link.href = "https://google.com";
}

간단한 접근이라면 옵셔널 체이닝을 사용할 수도 있습니다.

1
link?.focus();

✅ 정리

TypeScript에서 DOM을 다룰 때는 선택한 요소가 어떤 HTML 요소인지 타입으로 알려주는 것이 중요합니다.

  • querySelectorAll은 기본적으로 NodeListOf<Element>를 반환합니다.
  • Element는 넓은 타입이라 style, value 같은 속성을 바로 사용할 수 없습니다.
  • querySelectorAll<HTMLElement>()처럼 타입을 지정할 수 있습니다.
  • input, button, img처럼 태그별 전용 타입을 사용하면 더 안전합니다.
  • querySelectornull을 반환할 수 있으므로 조건문이나 옵셔널 체이닝을 함께 사용하면 좋습니다.

DOM 타입을 조금 더 구체적으로 지정해두면 TypeScript가 더 정확하게 도와줄 수 있습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

[TypeScript] 타입스크립트 기본 타입 정리

[JavaScript] classList로 클래스 추가, 삭제, 토글하기