[ Typescript ] - HTML변경과 조작 & 연산자 !

최문길·2023년 12월 21일
1

Typescript

목록 보기
9/23

HTML 조작과 변경

typescript로 연습용 div를 만들어 style을 주려고 했는데...

var red = 'red' as const // 값이자 타입

var div  =document.querySelector(".div")

div.style.color = red

원래 자바스크립트라면 정상적으로 작동 했을테지만...

typescript라서 그런지...

div 값이 null 될 수있으니 타입지정 똑디 하라고 친절하게 알려준다.

div에 mousehover를 하니


div의 타입이 Element | null 이 될수도 있다고 한다.



왜??

typescript는 javascript로 컴파일만 하지 브라우저와 node 환경에서 run 타임을 가지지 않는다.

그러므로 typescript compiler는 당연하게도 run타임을 가지기 전이므로 Element일수도 있고 null 일수 있어요 라고 말해주는 것일 뿐!


다시 돌아와서...

타입을 narrowing을 해줘야 하는데 몇 가지 방법이 있다.

  • assertion 사용
  • 옵셔널체이닝 사용
  • narrowing
  • strick을 끈다. - 이건아니지 않겠냐..

assertion 사용


var red = 'red' as const // 값이자 타입
var div  =document.querySelector(".div") as Element 
// div의 타입이 Element가 된다.

optional chaining


var red = 'red' as const // 값이자 타입
var div  =document.querySelector(".div")
div?.style.color = red

instanceof로 narrowing

var div  =document.querySelector(".div")
if(div instanceof Element) {
  div.style.color = red
}


그런데 optional chaining과 narrowing의 코드를 사용해서 style을 주려면 또다시 에러가 난다.

위와 같이 Element type에는 style이 존재하지 않는다고 ...

왜지??

HTMLElements inherit from Element which inherit from Node.
This means that your HTMLElement is simultaneously an instanceof all three. The fact that it is an HTMLElement means it has an interface that's contains methods only an HTMLElement would need like attachEvent.

stackoverflow에서...

위와 같이 HTMLElementNode에서 부터 상속받은 Element로 부터 상속된 것이기에 전반적으로 단지 무수히 많은 태그들 전부를 각 명명 할 수 없으니 Element 하나라는 General 한 타입을 명시 한것 같다..

이 말인 즉슨 type이 Element에는 style 이라는 속성이 없기에 조금더 narrowing 해주세요 라는 의미로 해석이 된다.

그러므로

var red = 'red' as const // 값이자 타입

// narrowing
var div   = document.querySelector(".div") ;
// Element가 아닌 HTMLElement로 || HTMLDivElement로 
if(div instanceof HTMLElement) { 
      div.style.color = red
}

// assertion
var div  =document.querySelector(".div") as HTMLElement
div.style.color = red

위와 같이 narrowing || assertion을 할 때 조금더 세분화하여 타입을 명시해주거나 narrowing 해주자!!

a 태그의 hre 속성을 바꿔보자

위와 똑같은 방법으로 네이버 링크를 카카오 링크로 바꿔보자

// index.html
<a id='link' href='https://naver.com' >링크</a>

// typescript
let link = document.querySelector('#link');
if (link instanceof HTMLElement) {
  link.href = 'https://kakao.com'
}

위 와같이 하면 되겠지 했지만 ;;

에러가 난다 .

Property 'href' does not exist on type 'HTMLElement

당황하지말고 HTMLElement타입에는 href 속성이 없다고 하니까
" 다른 타입으로 바꿔주자 " 생각하자

instanceof HTML이라고 쳐주면 알아서 에디터가 타입 추천을 해주는데 거기서 a 태그는 anchor 와 같으니까 HTMLAnchorElement를 찾아보면 나오는데 이 타입으로 narrowing 하면 조작 완료

let link = document.querySelector("#link");

if(link instanceof HTMLAnchorElement){
      link.href = 'https://kakao.com'
}

결론

html 태그 종류별로 정확한 타입명칭이 있다.

  • a 태그는 HTMLAnchorElement

  • img 태그는 HTMLImageElement

  • h4 태그는 HTMLHeadingElement
    .
    .
    ...

와 같이 정확한 타입이 있으므로 type 지정을 확실히 해주고 조작/변경 하자.

그리고 Narrowing 하는 방법중
instanceof 를 쓰면 가장 정확한 타입 narrowing을 할 듯하다.


그런데 위와 같은 방법 밖에 없을 까했는데

typescript에서
! 연산자를 사용 할 수도 있다.

! 연산자

의미는 : null이나 undefined가 될 수 없다라는 뜻을 품고 있다.

var div  =document.querySelector(".div") !

이렇게 하면 ! 를 붙이기 전에 타입은 Element | null 이었지만

Element 하나로 narrowing이 되는 것을 알 수 있다.

! 연산자의 사용처는

내가 짠 코드가 run 타임을 할 때 당연하게도 null | undefined가 안나오는 것을 알지만

complier는 run 타임 이전에 작동하는 것으로 type 추론이 명확하지 않았을 때 내가 슬쩍 넣어주는 걸로만 사용 해보자

0개의 댓글