Typescript - 6

hoin_lee·2023년 7월 27일
0

TypeScript

목록 보기
8/14

lib 컴파일러 옵션

lib 프로퍼티를 사용하면 타겟 런타임 환경을 설명하는 번들 라이브러리 선언 파일을 지정할 수 있다.
활성화 하지 않았을 때는 기본값 즉 DOM이 설정되어 있다.
기본적으로 Typescript는 document 및 DOM 조작 항목과 DOM API의 타입을 인지하는데 만약 lib의 주석처리를 해제하면 비활성화 된다.(맨 처음tsconfig 파일을 보면 "lib" : []이런식으로 주석처리가 되어있다)
그럼 [] 이렇게 초기화 되어 있으므로 기존 typescript 파일에 작성한 document 부분에 에러가 발생한다.(document 타입을 찾지못해 any로 설정됨)
이는 typescript 문서에서 확인할 수 있으며 DOM을 다시 추가하려면 []배열안에 "DOM"을 추가하자!

또한 es2021부턴 replaceAll가 추가되었는데 이를 사용하기 위해 target을 바꾼다면 es5에서 존재하다가 es2021에 오며 삭제된 기능들은 사용하지 못할 수 있다.
이때 lib 옵션에 DOM과 같이 "ES2021"와 같은 식으로 저장하면 둘 다 사용할 수 있다
하지만 꼭 수동으로 할필요는 없고 만약 이유가 있어 es5를 타겟으로 지정하고 다른 버전을 사용해야 겠다 싶으면 이런 방법이 있다 라고 알아놓자

NON_Null 단언 연산자

const btn = document.getElementById("btn")

javascript로 무언가를 만들어 봤다면 자주 봤을 이 코드에서 btn은 어떤 타입일까 생각할 수 있다.
직접 console.dir 찍고 마지막 prototype으로 봐보면 HTMLButtonElement라고 확인된다.
그렇다면 이게 반환타입일까? 그렇지는 않다! 확인해보면
btn:HTMLElement | null 로 확인된다. 왜그럴까?

일단 HTML요소 타입을 보면 제네릭 HTML요소이다. 아까 console로 확인했던 것처럼 Button과 같은 타입이 아니다
이유는 간단히 Typescript는 알 수 없기 때문이다. 기본적으로 Typescript는 런타임이 아닌 사전에 작동하기 때문이다
Id를 통해 추적 가능한다 하여도 그게 h1태그에 있을지 div태그에 있을지 모르기 때문에 getElementById가 반환하는 게 제네릭HTML요소이구나만 인지하는 것!

그렇기에 null도 존재하는지 안하는지 사전에 작동하기 때문에 몰라서 만약 없다면 null로 표기할게 하는 거와 같다
null값이 이전 React를 통해 프로젝트 작업할때 매우 짜증난 적이 많았다.
분명 존재하는 값이고 있는데 이놈의 null때문에 자꾸 ?연산자를 넣어서 해결은 했지만 정확한 이유를 몰랐었는데 다시 공부하면서 깨닫는 부분이다.

여기서 ?를 이용해 Javascript에게 넘기는 게 아닌 Typescript에서의 접근 방법이 있다.
non-null 단언 연산자인데 그냥 !이다

const btn = document.getElementById("btn")!

btn.addEventListener("click", ()=>{
  alert("Clicked")
})

const btn끝의 !가 절대 null이 되지 않는다고 typescript에 약속하는 것이다
하지만 ?연산자보단 조금 위험할 수는 있다.
그러니 값이 확실하게 존재하고 null이 아닐때 ?를 그만사용하고 싶다? 일때만 사용하자

Type Assertions(타입 단언)

타입 단언 개념은 TS에 선언하는 것으로 이 값을 다른 타입으로 취급하려 할 때 사용한다.
내가 확실한 타입 정보를 가지고 있고 TS의 정보가 부족한 상황에서 사용하면 유용하다.

약간 억지 예시를 넣는다면

let mystery:unknown = "Hello World!!!";

const numChars = mystery.length // unknown이기 때문에 length를 사용할 수 없다는 에러가 발생한다
const numChars = (mystery as string).length // 정상동작한다! 하지만 mystery의 타입을 확인하면 여전히 unknown이다

as를 통해 타입단언을 이용하고 실제 DOM에서 쓰이는 경우가 있다.(react 프로젝트시 몇번 이용했다! target의 id 속성을 자꾸 가져오지 못하는 경우가 있어서 as를 활용한 타입 단언으로 실행했다)

<input id="todoinput" type="text" />

이와 같은 input 태그가 있고 입력된 값을 꺼내오고 싶다.

const input = document.getElementById("todoinput")
const inputValue = input.value

보통 javascript로 가져오면 이런식으로 input값을 꺼낼 것이다. 그럼 Typescript는 어떻게 할까?

const input = document.getElementById("todoinput")!;
input.value // 접근하려면 HTML제네릭 요소엔 value가 존재하지 않는다는 에러가 생긴다

왜 에러가 생길까? 값은 HTML input요소에 존재하고 다른 HTML태그에는 존재하지 않는 경우도 많다.(image 등)
제네릭 HTML요소는 값을 가지지 않기에 에러가 생기는 것! 이를 typescript에게 단순한 HTML요소가 아니고 HTML input이라고 알려줘야 한다.

const input = document.getElementById("todoinput")! as HTMLInputElement;
const inputValue = input.value

이후 더이상 에러가 발생하지 않는다!

as를 대신해서 사용할 수 있는 구문이 있는데 <>이다

const input = document.getElementById("todoinput")!;
const inputValue = (<HTMLInputElement>input).value

이렇게 작성해도 에러가 발생하지 않는다. 다만 이 구문은 일반적이지 않고 JSX에서 동작하지 않으므로 react에선 에러가 발생한다

추가적인 이벤트 타입들

form 태그를 이용해 addEventListenersubmit을 했을 때 뒤의 콜백함수의 event 타입

  • SubmitEvent <- 아마 typescript가 자동으로 추적해줄 것이다.
    하지만 만약 다른 함수로 이동시켜서 사용한다면 typescript는 event를 추적할 수 없고 암묵적 any타입이라고 명시한다.
    이럴 땐 아래처럼 직접 입력해준다
function handleSubmit(event: SubmitEvent){
  event.preventDefault();
//....some code
}

이는 다른 이벤트 타입을 사용할 때도 마찬가지이다.

profile
https://mo-i-programmers.tistory.com/

0개의 댓글