코딩애플 Typescript - 타입스크립트로 HTML 변경과 조작할 때 주의점

김원종·2024년 4월 3일
0

TypeScript 학습

목록 보기
9/28

자바스크립트의 원래 목적은 html 조작과 변경이다. 그래서 타입스크립트를 써도 html 조작이 가능한데 일반 js를 쓸때와는 다른 점이 존재한다. 그부분에 대해서 알아보도록 하자.


알아보기 전 tsconfig.json 파일에 위 내용을 추가하자 strictNullChecks 을 추가해도 되고 strict라는 옵션이 몇개가 있는데 NullChecks도 그중 하나이므로 strict를 true로 바꿔도 똑같이 동작할 것이다.
strictNullChecks 는 간혹 null타입이 들어올때 엄격하게 체크해달라는 뜻이다.

위처럼 하려해보았는데 에러가 난다 타입이 union타입이라 에러가 발생하는 것이다. 왜 union타입일까? #title이라는 아이디를 잘 찾으면 값이 들어가지만 못찾으면? null이 들어갈것이다. 그렇기 때문에 확실한 타입이 아니라 Narrowing 이라는 작업이 필요하다.

이런식으로 간단한 글자 변경도 narrowin을 잘 해주어야한다. select로 찾은 요소는 항상 null일수도 있기 때문에 위처럼 해주어야 한다.


HTML 조작시 narrowing 방법 5개

1번 방법은 위에서 말한것처럼 null이 아니면을 확인해주면 된다.

  1. instanceof 연산자
    아마 가장 많이 사용하게될 연산자 이다. 오른쪽 Element 부분에 클래스명 같은것을 기입하고 왼쪽 제목 부분에는 오브젝트를 기입을 하면 해당 오브젝트가 오른쪽에 있는 클래스의 자식이냐 즉 instance이냐 그런것들을 확인해주고 그게 맞다면 true를 뱉어낼것이다.

  1. as키워드 사용
    한마디로 s키워드를 사용해서 사기를 치는것이다. 왼쪽 querySelector에 있는 요소의 타입을 Element로 간주해달라는 뜻이다. 그렇게 되면 null값이 들어와도 무조건 Element 타입으로 확정이 되기 때문에 narrowing이 가능해지는 것이다. 타입을 뒤집어 씌어 사기를 치는것도 narrowing으로 인정을 해준다. 하지만 as키워드는 그냥 사용하면 안된다. 비상시 혹은 100% 확신을 할때 사용하는 키워드이다.as를 사용하면 타입스크립트를 사용하는 이유가 없다.


4.오브젝트에 붙이는 ?.
innerHTML 로 자료를 뽑아서 변경을 할수 있는데 .앞에 ?를 넣어주면 제목에 innerHTML이 있으면 출력을 해주고 없으면 undefined를 뱉어내라고 하는것이다. 신문법인데 optional chaining 이라고 2020년 이후부터 사용가능한 문법이라고 한다.

5.무식한 해결책 tsconfig.json 조작
위에 옵션값중 NullCheck부분을 false로 바꾸던지 지워버리면 null값도 들어갈것이다.그럼 narrowing 없이 사용할수있지만 되도록 코드로 해보자.


위 내용들은 그냥 자바스크립트에서도 안정성을 위해 사용할수잇다.

자 그럼 이번에는 링크부분을 수정해보자.

이렇게 똑같이 수정하려 했지만 이번에는 에러가 발생한다.이유는 무엇일까?

href라는 속성이 Element에 없다는것이다. 왜냐 narrowing을 할때 상세하게 해주지 않아서 그렇다.

이런식으로 HTMLAnchorElement 라는것을 사용해서 정확하게 narrowing을 해줘야한다. 그래야 htef속성을 가져다 사용할수있다.

원리를 알아보자면 ts가 제공하는 HTML관련 타입들 기본타입 같은 것이 있는데 기본적으로 Element 타입 이 있는데 그것을 복제해서 만든 타입들이 있다. 이러한 타입들은 즉 Heading 태그 button태그 그것들을 조작하기위한 타입이다.

Element 타입안에는 별로 든게 없다. 즉 정의된게 별로 없다는 것이다.

하지만 HTMLAnchorElement타입이면 위 내용같은 내용을 가져다 사용할수 있게 정의가 되어 있다고 보면 된다.

그렇기 때문에 이런식으로 HTMLAnchorElement 을 사용해야 href를 조작할수 있는 것 이다.

버튼이벤트 주는것 또한 narrowing이 필요한데 위 처럼 ? 기호를 사용해 타입을 정해줄수잇다.


숙제1) 버튼을 누르면 이미지를 바꿔봅시다.

<img id="image" src="test.jpg">

html 안에 test.jpg를 보여주고 있는 이미지 태그가 있다고 칩시다.
이미지를 new.jpg 라는 이미지로 바꾸고 싶으면 자바스크립트 코드를 어떻게 짜야할까요?
성공여부는 크롬 개발자도구 켜면 src 속성이 잘 바뀌었는지 확인가능하겠죠?

나의 풀이

var imgs = document.querySelector('#image');

if(imgs instanceof HTMLImageElement){
    imgs.src='new.jpg'
}

센세 풀이

let 이미지 = document.querySelector('#image');
if (이미지 instanceof HTMLImageElement){
  이미지.src = 'change.jpg';
}
저는 html 요소를 찾고 이걸 HTMLImageElement 타입 맞냐고 확인해봤습니다.

이 경우 src 속성을 수정가능합니다.

숙제2) 바꾸고 싶은 html 요소가 많습니다.

<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a>

3개의 링크가 있는데 이 요소들의 href 속성을 전부 https://kakao.com으로 바꾸고 싶은 겁니다.

자바스크립트 코드를 어떻게 짜야할까요?

나의 풀이

let link2 = document.querySelectorAll('.naver');



link2.forEach((a)=>{
    if(a instanceof HTMLAnchorElement){
        a.href= 'https://kakao.com'
    }
})

센세 풀이

let 링크 = document.querySelectorAll('.naver');

링크.forEach((a)=>{
  if (a instanceof HTMLAnchorElement){
    a.href = 'https://kakao.com'
  }
})
querySelectorAll() 셀렉터를 쓰면 많은 요소를 한번에 찾을 수 있습니다. 

근데 이 경우 타입이 NodeListOf<어쩌구> 이렇게 나오는데 그냥 여러개 찾으면 이런 타입이 된다고 생각하면 됩니다.

그리고 forEach 반복문을 이용해서 찾은 요소마다 각각 href 속성을 변경해줬다고 합니다. 

 

 

let 링크 = document.querySelectorAll('.naver');

for (let i = 0; i < 3; i++){
  let a = 링크[i];
  if (a instanceof HTMLAnchorElement){
    a.href = 'https://kakao.com'
  }
} 
일반 for 반복문을 쓸 경우 변수를 만들어줘야 매끄럽게 narrowing이 가능합니다. 
profile
개린이

0개의 댓글