본문 바로가기
TIL

ts 브랜딩 타입 (태그드 타입) vs enum vs 리터럴

by 은지:) 2024. 6. 28.
728x90
반응형

같은 number 타입이지만 kg, cm로 성질이 다른 값들...

좀더 구체적인 타입을 정의하고 싶을 때 이렇게 씀

 

타입 안정성을 올릴 수 있는 방법 중 하나인 브랜딩 타입

 

const length  = 80 as number & {__brand:"cm"}; // cm 
const weight = 90 as number & {__brand:"kg"} // kg



function showWeight (weight:number & {__brand:"kg"}) {
  return console.log("weight ", weight)
}


function showLength (length:number & {__brand:"cm"}) {
  return console.log("length ", length)
}

showWeight(weight)
showLength(length)

showWeight(12 as number & {__brand:"kg"})

const sum :number = weight + length 
console.log(sum)

 

같은 number이기 때문에 더하기는 됨

 

 

 

 

보통 이렇게 정의해놓고 쓴다함

interface Brand<T, B> {
 value: T;
 _type: B;
}

type Length = Brand<number, "cm">;
type Weight = Brand<number, "kg">;

 

const length: Length = { _type: "cm", value: 80 };
const weight: Weight = { _type: "kg", value: 90 };

 

 

 

확장 버전

interface Length extends Brand<number, "cm"> {
  unit: "centimeter";
}

interface Weight extends Brand<number, "kg"> {
  unit: "kilogram";
}
const length: Length = { _type: "cm", value: 80, unit: "centimeter" };
const weight: Weight = { _type: "kg", value: 90, unit: "kilogram" };

 

function showWeight(weight: Weight) {
  console.log("weight", weight.value, weight.unit);
}

function showLength(length: Length) {
  console.log("length", length.value, length.unit);
}

 

 

 

vs 

 

음 enum이랑 똑같은 거 아닌가.... 하는 느낌

 

enum과 브랜딩 타입 모두 타입을 구체화하는건 맞음

하지만 다름

 

enum은 관련된 상수들의 집합임

브랜딩 타입은 동일한 기본타입을 구체화하는 거임

 

 

위의 예시를 enum으로 쓴다면

enum Unit {
  CM = "cm",
  KG = "kg"
}

interface Length {
  value: number;
  unit: Unit.CM;
}

interface Weight {
  value: number;
  unit: Unit.KG;
}

const length: Length = { value: 80, unit: Unit.CM };
const weight: Weight = { value: 90, unit: Unit.KG };

function showWeight(weight: Weight) {
  console.log("weight", weight.value, weight.unit);
}

function showLength(length: Length) {
  console.log("length", length.value, length.unit);
}

 

 

성질 비슷한 것들 묶어놓는 느낌

근데 요즘 enum 잘 안 씀

 

이유는 라인에서도 알려주고 다른 참고 블로그 많음

https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking

https://mugglim.tistory.com/9

 

 

1. enum 은 숫자형일 때 자동적으로 값이 할당됨

enum Direction {
  Up,    // 0
  Down,  // 1
  Left,  // 2
  Right  // 3
}

console.log(Direction.Up);    // 출력: 0
console.log(Direction.Down);  // 출력: 1
console.log(Direction.Left);  // 출력: 2
console.log(Direction.Right); // 출력: 3


let myDirection: Direction = Direction.Up;
console.log(myDirection);  // 출력: 0

myDirection = 5;  // 허용됨, 하지만 의도하지 않은 값
console.log(myDirection);  // 출력: 5

 

=> vscode에서 오류는 띄워주는데, 실행은 되는 거 같음

=> 이거 대응하기 위해서 이렇게 const를 쓴다고 하는데

const enum Direction {
  Up,    // 0
  Down,  // 1
  Left,  // 2
  Right  // 3
}

왜 나는 이렇게 써도 값이 할당되지...?

다른 곳에서는 이렇게 쓰면 된다고 함

근데 저것도 문제점이 있음

 

1. babel-plugin-const-enum 설정이 필요하다고 함

2. 문자열 값을 유니코드로 생성한다고 함 (빌드 파일 커짐)

 

 

https://mugglim.tistory.com/9

const enum EnumKeyboard {
  "GREETING" = "안녕하세요. 반가워요!!"
}
console.log(EnumKeyboard['GREETING']);

/* JS */
console.log("\uC548\uB155\uD558\uC138\uC694. \uBC18\uAC00\uC6CC\uC694!!" /* 'GREETING' */);

 

=> 여기에 대응하는 방법으로는

그냥 객체 만들어서 as const 붙인 다음에 이걸  type IType = typeof 객체 이름 

요렇게 쓰신다고 함

 

 

 

 

2. 트리 셰이킹 이슈

 

트리 셰이킹 :

=> 빌드 파일 만들 때 쓰지 않는 코드들은 제거해 주는 거. 경량화 목적임

=> 웹팩에서는 ES6 모듈 시스템 사용하고 mode : production 하면 자동으로 활성화 함

 

웹팩 이외에도 빌드 툴들이 빌드 할 때 거치는 과정 중 하나임

타입도 마찬가지로 컴파일 단계에서 타입 검사만 하고 사라짐

 

근데  enum은 자바스크립트 코드로 컴파일 되기 때문에 빌드 파일에 남아 있음  <= 경량화가 안됨 최적화된 번들이 아님

 

 

 

 

enum 은 타입인데.. 타입 같지 않는 느낌...

그냥 다른 거 쓰는 게 나음

 

저러한 한계 찐 대안법

리터럴 타입과 유니언 타입

 

type Unit = "cm" | "kg";

function printUnit(unit: Unit) {
  console.log(unit);
}

printUnit("cm");  // 올바른 호출
printUnit("kg");  // 올바른 호출

 

이렇게 쓰면 됨

 

 

 

enum 요즘 안 쓴다고 해서 필요할 때 저렇게 썼는데

왜 안 쓰는지 알게 됨

진짜 쓸 필요 없었네...

 

 

 

 

728x90
반응형

댓글