
먼저 HTML을 조작하기 전에 tsconfig.json 파일을 열어서 strickNullChecks 옵션을 true로 바꾼다.
혹은 그냥 "strict" : true 이런걸 써두면 strickNullChecks 옵션도 자동으로 true로 켜집니다.
많은 환경에서 null이 들어올 경우 체크해주는 옵션을 켜고 코드짭니다. 변수 조작하기 전에 이게 null인지 아닌지 캐치해낼 수 있으니까요. 특히 html 조작할 때 셀렉터로 찾으면 null 어쩌구가 많이 발생하는데 그거 잡을 때도 도움됩니다.
// tsconfig.json 파일
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"strictNullChecks": true
}
}
html파일 준비
<!-- index.html -->
<h4 id="title">안녕하세요</h4>
<a href="naver.com" class="link">링크</a>
<button id="button">버튼</button>
<script src="변환된 자바스크립트파일.js"></script>
// 에러나는 코드
let subject = document.querySelector("#title");
subject.innerHTML = "반가워요"
자바스크립트에서는 에러가 나지 않지만 타입스크립트에서는 에러가 난다.(추가한 strict 옵션 때문에) subject 변수가 null 일 수 있기 때문.
이유는 셀렉터로 html을 찾으면 타입이 Element | null 이기 때문이다.
위의 코드에서 subject 변수가 union type(Element | null)이기 때문에 에러가 난다.
let subject = document.querySelector('#title');
if (subject != null) {
subject.innerHTML = "반가워요"
}
if 문으로 범위 좁히기
let subject = document.querySelector('#title');
if (subject instanceof HTMLElement) {
subject.innerHTML = "반가워요"
}
가장 많이 쓰는 방법
instanceof 라는 연산자를 쓰는 것인데 우측에 HTMLElement 입력하면 그 타입인지 체크해줍니다.
let subject = document.querySelector('#title') as HTMLElement;
subject.innerHTML = "반가워요"
document.querySelector("#title")을 element로 간주한다.
as 키워드를 쓰면 타입을 하나로 만든다.(비추천)
타입을 HTMLElement 혹은 그냥 Element 로 만든다고 하면 된다.
let subject = document.querySelector('#title');
if (subject?.innerHTML != undefined) {
subject.innerHTML = "반가워요"
}
?는 왼쪽에 있는 object 자료안에 .innerHTML이 존재하면 그거 써주시고 없으면 undefined(있냐 없냐)
narrowing할 때 && 연산자로 undefined 체크하기 귀찮을 때 간혹 사용됩니다.
자바스크립트에서 바꾸기
let 링크 = document.querySelector(".link");
링크.href = "https://kakao.com";
타입스크립트에서 바꾸기
let 링크 = document.querySelector('#link');
// 에러나는 코드
// if (링크 instanceof HTMLElement) {
// 링크.href = 'https://kakao.com'
// }
if (링크 instanceof HTMLAnchorElement) {
링크.href = 'https://kakao.com'
}
HTMLElement을 사용하면 HTMLElement 타입은 href 속성 없다고 에러 발생
html 태그 종류별로 정확한 타입명칭이 있습니다.
a 태그는 HTMLAnchorElement
img 태그는 HTMLImageElement
h4 태그는 HTMLHeadingElement
button 태그는 HTMLButtonElement
등..
정확한 타입으로 narrowing 해야 html 속성 수정이 된다.(자동완성 기능 활용)
<img id="image" src="test.jpg">
let img = document.querySelector('#image');
if (img instanceof HTMLImageElement){
img.src = 'change.jpg';
}
HTMLImageElement 타입을 확인해야 src 속성 수정 가능
<a href="naver.com" class="link">링크</a>
<a href="naver.com" class="link">링크</a>
<a href="naver.com" class="link">링크</a>
let links = document.querySelectorAll(".link");
links.forEach((link)=>{
if (link instanceof HTMLAnchorElement) {
link.href = "https://kakao.com"
}
})
타입스크립트에서 쓸 수 있는 HTML 타입들은
Element, HTMLElement, HTMLAnchorElement 등이 있음.
Element에 들어있는걸 복사해서 몇개 더 추가해서 HTMLElement 타입을 만들어놨음
HTMLElement에 들어있는걸 복사해서 몇개 더 추가해서 HTMLAnchorElement 타입 만들어 놨음
셀렉터로 찾으면 Element 타입이 부여됨.
Element 타입은 광범위한 타입(일반 html 태그의 특징을 정리해둔 타입이라 .href .src 등 상세 속성 없음)
반면 HTMLAnchorElement, HTMLImageElement, HTMLHeadingElement 등 이런 형식은 상세한 타입.
이 타입은 "href, style, class, id 이런 속성을 가질 수 있다~" 라고 타입이 정의되어있습니다.
a태그에 HTMLAnchorElement 라는 타입을 쓸 수 있는지 instanceof 키워드로 확인해야 한다.
확인하는 과정을 narrowing으로 인정해줌
// 에러발생
let 버튼 = document.getElementById('button');
버튼.addEventListener('click', function(){
console.log('안녕')
})
버튼이라는 변수가 null 일 수도 있어요 라고 에러 발생
let 버튼 = document.getElementById('button');
버튼?.addEventListener('click', function(){
console.log('안녕')
})
?로 optional chaining 하면 에러 안남
출처: coding apple