TypeScript: 타입 형변환 (type assertions)

Kyungs·2021년 11월 15일
0

TypeScript

목록 보기
3/3
post-thumbnail
post-custom-banner

TypeScript에서 이전 코드에 선언해 두었던 타입을 변경하기 위해 as를 사용할 수 있다. 타입을 검사하여 오류를 잡아내는 것이 TypeScript를 사용하는 이유인만큼 코드 중간에 타입을 변경하는 것이 안전하다고 하기는 어렵지만, 그래도 기능을 구현하다보면 타입을 변경해야 하는 경우가 있을 수 있다.

as

명확하게 다른 타입으로 변경하기 위해서는 unknown으로 변경 후 변경하고자 하는 타입으로 변경할 수 있다. 그러나 서로 관계가 있는 타입으로 변경하기 위해서는 unknown을 생략할 수 있다.

const num: number = 0;

...

// number 와 string은 관계가 없는 명확히 다른 타입이기 때문에 unknown을 생략할 수 없다.
(num as string).substr(0, 5); // error! (의도적으로 바꾼 것이라면 unknown을 추가하라는 오류가 뜬다.)
(num as unknown as string).substr(0, 5); // okay


const div = document.createElement('div');

...

// HTMLElement와 HTMLDivElement는 서로 부모-자식 관계이기 때문에 unknown을 생략할 수 있다.
(div as HTMLElement).textContent; // okay
(div as unknown as HTMLElement).textContent; // okay

Event 형변환

이전 글에서 any를 사용하지 않고 타입을 지정할 수 있는 몇 가지 방법에 대해 포스팅을 했었다. 그 중 하나가 React.ChangeEvent에 관련한 것이었다.

e: React.ChangeEvent<HTMLInputElement>를 사용하면 input 태그 안에 있는 value 값을 바로 접근할 수 있기 때문에 onChange 이벤트를 비교적 쉽게 사용할 수 있다. 다만, onClick 이벤트라면 얘기가 달라질 수 있다. 아래 코드에 예시가 있다.

import React from 'react';

const App = () => {
  const thisText = 'text';
  const getDivText = (e: React.MouseEvent<HTMLDivElement>) => {
    return e.target.textContent; // 오류: 'EventTarget' 형식에 'textContent' 속성이 없습니다.
  }
  
  const getInputText = (e: React.ChangeEvent<HTMLInputElement>) => {
    return e.target.value; // okay
  }
  
  return (
    <>
      <div onClick={getDivText}>{thisText}</div>
      <input onChange={getInputText} value={thisText}></input>
    </>
  );
}

위 예시에서 onChange를 사용하여 ChangeEventtarget을 사용하면 value, textContent등 여러가지 속성들을 사용할 수 있지만, MouseEventtarget에 존재하는 속성이라고는 addEventListener, dispatchEvent, removeEventListener 밖에 없다.

그렇다고 TypeScript에서 MouseEventtargettextContent 등의 속성들을 사용할 수 없는 것은 아니다. 이 때 필요한 것이 바로 형변환이다. 아래에 위 코드를 수정한 예시가 있다.

import React from 'react';

const App = () => {
  const thisText = 'text';
  const getDivText = (e: React.MouseEvent<HTMLDivElement>) => {
    return e.target.textContent; // 기존 코드: 오류
    return (e.target as HTMLElement).textContent; // 수정 코드: okay 
  }
  
  return (
    <div onClick={getDivText}>{thisText}</div>
  );
}

HTMLElement에는 textContent 뿐만 아니라 className, id 등의 속성들이 모두 포함되어 있다. 기존에는 이벤트가 MouseEvent로 정의되어 있어서 그 target의 속성을 제한적으로만 사용할 수 있었는데, 수정된 코드에서는 이벤트의 target 자체의 타입을 HTMLElement로 형변환 함으로써 다른 속성들을 사용할 수 있도록 만들어주는 것이다.

이러한 형변환은 기존에 선언한 타입을 변경하는 것이기 때문에, 특히 협업을 할 때에는 (대부분의 프로젝트가 협업으로 진행되겠지만..!) 주의해서 사용할 필요가 있다. 기존 타입을 선언했을 때의 의도와 전혀 다르게 사용될 가능성이 있기 때문이다.

참고 자료

TypeScript never, any, 타입 캐스팅
TypeScript type assertions 공식 문서

post-custom-banner

0개의 댓글