본문 바로가기
TS/TS(애플코딩)

함수와 methods에 type alias 지정하는 법과 타입스크립트로 HTML 변경과 조작할 때 주의점

by Hyeon_E 2023. 8. 6.

함수와 methods에 type alias 지정하는 법

function type도 저장가능

함수 타입도 type alias로 저장해서 쓸 수 있음

예를 들어 숫자 두개를 파라미터로 입력하고 숫자를 return 하는 함수를 별명을 지어서 사용한다면

 

type NumOut = (x : number, y : number ) => number ;

 

이것을 함수 만들때 사용하려면 function 함수이름: NumOut(){} 식은 불가능

function 키워드에서는 ()랑 오른쪽 타입지정만 가능하기 때문에 

 

type NumOut = (x : number, y : number ) => number 
let ABC :NumOut = function(x,y){
  return x + y
}

 

함수를 만들 때 let 함수명 = function(){} 식으로 사용할 수 있기 때문에

함수명 오른쪽에 함수명 : 타입별명으로 지정해서 사용하는 것

 

methods 안에 타입지정하기

object 자료 안에 함수도 마음대로 집어 넣을 수 있음

 

let 회원정보 = {
  name : 'kim',
  age : 30,
  plusOne (x){
    return x + 1
  },
  changeName : () => {
    console.log('안녕')
  }
}
회원정보.plusOne(1);
회원정보.changeName();

 

위의 예시를 보면 plusOne과 changeName 함수를 object 자료에 집어넣었음

arrow function, 일반함수 전부 object 안에 맘대로 집어넣을 수 있음 넣은 함수들은 똑같이 점찍어서 사용가능

 

type Member = {
  name : string,
  age : number,
  plusOne : ( x :number ) => number,
  changeName : () => void
}

 

타입스크립트로 HTML 변경과 조작할 때 주의점

strictNullCheck 옵션 키기

많은 환경에서 null이 들어올 경우 체크해주는 옵션을 켜고 코드를 짬

변수 조작하기 전에 이게 null인지 아닌지 캐치해낼 수 있기 때문

 

#tsconfig.json
{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "strictNullChecks": true
    }
}

 

 

"strict" : true로 해두면 strickNullChecks 옵션도 자동으로 true로 켜짐

 

HTML 파일 준비

<!-- index.html -->
<h4 id="title">안녕하세요</h4>
<a href="naver.com">링크</a>
<button id="button">버튼</button>

<script src="변환된 자바스크립트파일.js"></script>

 

HTML 찾고 변경해보기

<h4> 제목을 다른 글자로 변경하면

 

let 제목 = document.querySelector('#title');
제목.innerHTML = '반갑소'

 

JS에서는 변경이 되지만 TS는 에러가 남 에러는 "제목이라는 변수가 null일수 있습니다"

strict 옵션으로 인해 에러가 나는데

이유는 셀렉터로 html을 찾으면 타입이 Element | null이기 때문(html을 못찾을 경우 null)

그래서 TS는 확실하지 않다고 생각하기 때문에  조작하고 변경하는걸 금지하는 것

 

여러가지 해결책

1. narrowing

let 제목 = document.querySelector('#title');
if (제목 != null) {
  제목.innerHTML = '반갑소'
}

 

2. 더 좋은 instanceof 사용하는 narrowing 방법

let 제목 = document.querySelector('#title');
if (제목 instanceof HTMLElement) {
  제목.innerHTML = '반갑소'
}

 

instance라는 연산자를 쓰는 것인데 우측에 HTMLElement를 입력하면 그 타입인지 에크해줌

 

3. assertion

let 제목 = document.querySelector('#title') as HTMLElement;
제목.innerHTML = '반갑소'

 

as키워드를 사용하는 것 임시이기 때문에 좋지 않음

 

4. optional chaining 연산자

let 제목 = document.querySelector('#title');
if (제목?.innerHTML != undefined) {
  제목.innerHTML = '반갑소'
}

 

optional chaining은 js 신문법으로 2020년 이후 브라우저들은 ?. 연산자를 이용 가능함

object에서 자료를 뽑을때 object.무언가로 무언가에 대한 자료를 뽑는데

object?.무언가로 뽑으면 무언가라는 자료가 object에 존재하면 그것을 주시고 없으면 undefined 남겨달라는 뜻

그래서 narrowing할때 && 연산자로 undefined 체크하지 않고 ?. 연산자를 사용하면 쉬움

 

위에 예시에서는 왼쪽에 있는 object 자료안에 .innerHTML이 존재하면 그것을 쓰고 없으면 undefined를 남기라는 뜻

 

5. strict 설정 false

null 체크가 문제이기 때문에 설정을 끄면 에러가 안남

 

가장 좋은 방법은 instanceof 연산자를 쓰는 것

 

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

html 파일에 <a href="naver.com"></a> 이런 태그가 있는데 href 속성을 바꾸고 싶다면

셀렉터로찾고.href = 'https://kakao.com'로 쓰면 됨

 

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

 

TS로 할 경우 HTMLElement 타입은 href 그런 속성 없다고 에러가 남

이럴 경우

 

let 링크 = document.querySelector('#link');
if (링크 instanceof HTMLAnchorElement) {
  링크.href = 'https://kakao.com'  //잘됨
}

 

이렇게 하면 에러가 나지 않음

HTML 태그는 종류별로 정확한 타입명칭이 있음

a 태그는 HTMLAnchorElement, img 태그는 HTMLImageElement, h4 태그는 HTMLHeadingElement 등등

 

왜 정확한 명칭으로 해야 하는 이유

타입스크립트에서 쓸 수 있는 HTML 타입들은 Element, HTMLElement, HTMLAnchorElement 등이 있는데 

Element에 들어있는걸 복사해서 몇개 더 추가해서 HTMLElement 타입을 만들어놨고

HTMLElement에 들어있는걸 복사해서 몇개 더 추가해서 HTMLAnchorElement 타입을 만들었음

 

셀렉터로 대충 찾으면 Element 타입이 부여가 됨

아직 이 태그가 뭔지 몰라서 그냥 광범위한 타입하나를 대충 지정해주는 것

이건 광범위한 그냥 일반 html 태그의 특징을 정리해둔 타입이기 때문에 안에 .href .src 들어가 있지 않음

 

반면 HTMLAnchorElement 좀 더 상세한 타입

이 타입은 "href, style, class, id 이런 속성을 가질 수 있다고 타입이 정의되어있음

그래서 a태그에게 어울리는 타입인 HTMLAnchorElement 라는 타입을 쓸 수 있는지 instanceof 키워드로 확인해야함

확인하는 과정을 narrowing으로 인정해 주는 것

 

이벤트리스터 부착해보기

let 버튼 = document.getElementById('button');
버튼.addEventListener('click', function(){
  console.log('안녕')
})

 

TS로 에러가 남 버튼이라는 변수가 null일수도 있기 때문

이런경우 narrowing을 사용할 수도 있지만

 

let 버튼 = document.getElementById('button');
버튼?.addEventListener('click', function(){
  console.log('안녕')
})

 

이런 해결법도 있음 addEventListener 함수 붙일때 물음표도 붙이는 것인데 버튼이라는 변수가 없을 경우 그 자리에 undefined를 내보내고 HTMLElement로 잘 있으면 addEventListener()를 잘 부착해주기 때문에 이것도 일종의 narrowing이라고 보면 됨 그렇기 때문에 에러가 안남

 

댓글