[Typescript pair study] 기초 타입 세션 ② enum, intersection, type assertion 등

이민선(Jasmine)·2023년 5월 7일
2
post-thumbnail

이번주는 2번째 세션!

이번 시간에도 역시 저번주와 마찬가지로 각자 만들어온 소스코드를 공유하고 설명 및 질의응답하는 시간을 가졌다.

이수민
1. intersection
2. type inference

이민선
1. discriminated union
2. enum
3. type assertion

이번 포스팅에서도 새로 알게된 것들 + 중요했던 type들 + 흥미로웠던 것들 위주로 정리해보려고 한다.

💡 나의 파트

- enum type은 권장되지 않는다.

enum에는 여러 종류가 있지만, 그 중에서도 많이 사용되곤 하는 것이 문자열 열거형(string enums), 숫자 열거형(numeric enums)이 있다.

// 문자열 열거형 (string enums)
  enum Day {
    MON = "월",
    TUE = "화",
    WED = "수",
    THU = "목",
    FRI = "금",
    SAT = "토",
    SUN = "일",
  }

  // 숫자 열거형(numeric enums)
  enum Response {
    No,
    Yes,
  }

숫자 열거형에서는 문자열 열거형과 달리, 값을 따로 지정해주지 않으면 숫자 값이 지정된다. 위의 예시에서 No의 값은 0이고 Yes의 값은 1이다. 물론 숫자를 자유롭게 값으로 지정도 가능하다.

원래 드림코딩에서는 enum이 권장되지 않는 이유가 enum 내에서 지정한 type 외의 value로 재할당이 가능하다고 배웠었다. 그런데 그건 typescript 2.4 버전 이전의 이야기이고, 그 이후에는 read-only 변수라고 에러가 뜨긴 한다.

그럼에도 불구하고 enum type은 권장되지 않는다고 한다. 그 이유가 무엇일지 궁금해서 공부를 해봤다.

가장 중요한 이유로 꼽히는 게 tree-shaking이 안되는 점이라고 한다.

tree-shaking이 무엇인가요?

프론트엔드 프레임워크에서 주로 사용되는 자바스크립트 코드 최적화 기술 중 하나이다. 프로젝트에서 사용하지 않는 코드(함수, 변수, 모듈 등)를 자동으로 제거하여 번들 크기를 줄이는 기술이다.

webpack, rollup 등 빌드 도구에서 코드의 의존성 트리를 분석하여 사용되지 않는 코드를 식별하고 제거해야 한다. tree-shaking이 이루어질 경우, 자바스크립트 엔진의 코드 파싱 및 실행 속도 향상, 초기 로드 속도 개선, 브라우저 캐시 효율성 향상 등의 이점이 있다.

그런데 enum을 사용하면 번들링할 때 tree-shaking이 제대로 되지 않을 수가 있다. js로 트랜스파일할 때 IIFE를 포함한 코드가 되는데, Rollup 등 번들러는 이를 사용하지 않는 코드라고 판단을 못하기 때문이다. 결국 사용하지 않는 코드인데도 최종 번들에 포함이 되어버릴 수도 있다.

참고 :
[LINE Engineering] TypeScript enum을 사용하지 않는게 좋은 이유를 Tree-shaking 관점에서 소개합니다.
https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking

물론 const enum이 도입되어 tree-shaking이 향상되기는 했지만, 웬만하면 union type 사용하는 게 가장 좋다고 한다.

- type assertion은 권장되지 않는다.

type assertion도 역시 되도록이면 사용하지 않는 것이 좋다. typescript 사용하는 이유가 typescript가 알아서 type 적절한지 평가해주기 때문에 안정적으로 코드를 짤 수 있다는 점인데, 내가 typescript compiler한테 "이거 문자열 맞아!" "이거 숫자 맞으니까 가만히 있어!"라고 외치는 격이나 다름 없다.
예전에 이 사실을 모를 때 type assertion을 사용했던 나쁜 예시가 생각이 나서 스터디에도 가져와봤다. ㅎㅎㅎㅎ

과거에 내가 사용했던 나쁜 예시

const date = new Date();
  const year = date.getFullYear();
  const month = date.getMonth();

// 매 달의 마지막 날
  type LastDate = 28 | 29 | 30 | 31;

  const lastDateOfMonth: LastDate = new Date(
    year,
    month + 1,
    0
  // 마지막 날은 LastDate 맞아!!! 라고 외치는 중 👻
  ).getDate() as LastDate;

달력 만들기 프로젝트를 할 때 처음에 썼던 코드이다. 매 달의 마지막 날은 28, 29, 30, 31일로 무조건 끝나게 되어 있으니 union type을 지정해주려고 했는데, lastDateOfMonth 변수에 type을 지정하니 type에러가 나는 것이었다.

https://velog.io/@jasmine0714/%ED%86%A0%EC%9D%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%8B%AC%EB%A0%A5-%EB%A7%8C%EB%93%A4%EA%B8%B0

new Date(year, month + 1, 0).getDate()는 number type이어서 내 맘대로 LastDate type을 지정하면 안된다고 한다. 그래서 type error를 없애려고 type assertion을 사용했었다.

나중에 알게 되었지만, 정말 불가피할 때 말고는 type assertion을 쓰지 않는게 좋다고 한다. 불가피라는 단어가 너무 주관적이어서 아직 내 스스로 저기에서 type assertion을 사용하는 게 옳은지 자체 판단은 못하겠다. 하지만 확실한 건 더 나은 방법으로 type을 줄 수가 있다는 것이다.

타입 가드 함수라는 게 있다고 한다!

// 타입 가드 함수
  function isLastDate(num: number): num is LastDate {
    return [28, 29, 30, 31].includes(num);
   }
  // 타입 가드 함수가 true를 return 했는지 확인함.
   if (!isLastDate(lastDateOfMonth)) {
     throw new Error("마지막 날짜가 유효하지 않습니다.");
    } else {
     console.log(${month + 1}월의 마지막 날짜는 ${lastDateOfMonth}일입니다.);
    }
  }

숫자가 LastDate인지 boolean type을 return하는 num is LastDate 타입의 함수를 만드는 것이다.

typescript 시작 전에는 type을 주는 방법의 폭이 이렇게 넓은지 몰랐던 것 같다. 이렇게 하나둘 씩 알게되니 아주 좋군!

💡 수민님 파트

- intersection은 AND 개념이다.

union이 or의 개념이라면, intersection은 AND의 개념이다. &를 사용하여 특정 변수에 여러개의 type을 동시에 지정할 수도 있다.

// 2가지의 type이 있고
  type Information1 = {
    name: string;
    age: number;
  }

  type Information2 = {
    hobby: string[];
    job: string;
  }

// &을 활용하여 2가지 type의 합집합 개념인 type이 생긴다.
  type Person = Information1 & Information2;

// girl이라는 변수는 name, age, hobby, job의 속성을 모두 가진다.
 const girl : Person = {
    name: 'Amy',
    age: 12,
    hobby: ['watching movie', 'running', 'cooking'],
    job: 'developer',
  }

- type inference

변수를 선언할 때 초기값이 있다면 typescript는 초기값을 기반으로 변수의 타입을 추론한다.

 let day = 13; //따로 타입을 명시하지 않아도 number type으로 지정된다.

여러 type이 섞여 있는 배열 또한 typescript compiler가 알아서 type 추론을 해준다.

// number 또는 string 또는 null 값이 원소가 될 수 있는 배열이다.
let arr = [0, 9, 'a', null];
// number, string, null 3개 중에 하나로 재할당 가능하다.
arr[0] = true;
arr[1] = null;

이로써 세션2까지 기초 타입을 한번 씩 다뤄보았다!! 한 번 쭉 개념들을 복습하니 그냥 강의를 들었을 때보다 스터디 할 때마다 머릿속에 잘 각인이 되고 있어서 아주 좋다 👏🏻👏🏻👏🏻👏🏻👏🏻

이제 우리 스터디에서는 다음주부터 코드스테이츠 js과제였던 my_Agora_States를 typescript template으로 리팩토링하려고 한다! 각자 리팩토링을 진행하면서, 어느 상황에서 어떤 type을 주었는지 공유하는 시간을 가질 것이다. (ex. event 객체, state에는 어떤 식으로 type을 주었는지)

📢 수민님 이번주도 수고 많으셨습니다~~! 주말 이용해서 스터디 과제 열심히 해보고 다음주에 뵈어요!! 화이팅팅!! 😊👍

profile
기록에 진심인 개발자 🌿

1개의 댓글

comment-user-thumbnail
2023년 5월 7일

화이팅티이리ㅣ팅팅!!!😆💪

답글 달기