TypeScript 브랜딩 기법 (원시 타입 구분하기)

최민경·2024년 7월 3일
2
post-thumbnail

서론

타입스크립트는 자바스크립트에 타입 시스템을 도입해 개발자의 실수를 줄이고, 코드의 가독성을 높이며, 프로그램을 실행하지 않아도 개발 과정의 유효성을 판단할 수 있게 한다.
이 때 안정성을 강화하며 유용한 기법이 브랜딩 기법이다

브랜딩 기법

브랜딩 기법이란?

동일한 기본 타입이 있을 때 타입 시스템을 보다 정밀하게 사용하기 위해 타입에 식별자를 추가해 타입을 더 구체적으로 구분해 타입 안정성을 강화하는 방법이다.

원시 타입

const length = 40;	// cm
const weight = 40;	// kg

function showWeight(weight: number) {
  console.log(`Weight: ${weight}`);
}

function showLength(length: number) {
  console.log(`Length: ${length}`);
}

showWeight(len);
showLength(weight);

lengthweight cm와 kg으로 서로 다른 단위를 가지고 있지만 둘 다 number 기본 타입이다.
그렇기 때문에 잘못된 함수에 전달하더라도 같은 타입이므로 에러가 발생하지 않으며, number 타입 이외에 정보를 가지고 있지 않기 때문에 변수 이름에 의존해야 한다.

브랜딩 기법

type Length = number & { __brand: 'cm' };
type Weight = number & { __brand: 'kg' };

const length = 80 as Length;
const weight = 80 as Weight;

function showWeight(weight: Weight) {
  console.log(`Weight: ${weight}`);
}

function showLength(length: Length) {
  console.log(`Length: ${length}`);
}

showLength(length);
showWeight(length); // error
showLength(weight);
showWeight(weight); // error

type을 통해 lengthweight의 타입을 각각 정의한다.
원시 타입과__brand 라는 속성을 추가해 각 타입을 구분한다.

const length = 80 as Length;
const weight = 80 as Weight;

위에서 정의한 타입은 as로 구분해줘야 한다.

as : 타입 단언을 위해 사용하는 키워드
컴파일 단계에서만 영향을 미쳐, 컴파일러에게 명시적으로 알리는 역할
런타임 단계에서 아무런 영향을 미치지 않아, 타입 단언을 통해 발생하는 에러는 런타임 에러로 발생한다.
타입스크립트보다 내가 타입을 명확하게 알고 있을 때만 활용한다고 생각하면된다.

const length: Length = 80

와 같이 작성할 경우에는 타입스크립트가 80과 Length 타입이 일치하지 않는다고 판단해 오류를 발생시키기 때문이다.

실제 예시

type Brand<Key extends string, Value> = Value & { __brand: Key } 

type Length = Brand<'cm', number>
type Weight = Brand<'kg', number>
type Address = Brand<'Address', string>
type Tel = Brand<'Tel', string>

공통된 Brand 타입을 생성해 타입을 브랜딩해줄 수 있다.

단점

  • 타입 단언 as 를 사용하는 경우가 많아 잘못된 타입 단언을 사용하면 런타임 에러로 이어질 수 있어 타입스크립트의 장점인 타입 안정성을 해칠 수 있다.
  • 런타임에는 아무런 영향을 주지 않기 때문에 실제 타입 안정성을 보장하지 못한다.
  • 기본 원시 타입에 대한 연산이나 함수를 그대로 사용할 수 있지만, 그 경우에는 결과가 원시 값으로 나타나 브랜딩한 타입을 결과로 원한다면 래핑 함수를 추가로 만들어줘야 하는 불편함이 있다.

결론

  • 단위가 중요한 경우 : 화폐 단위와 같이 단위를 명확하게 구분해야 할 때
  • API 호출 시 파라미터를 구분 : 여러 API 엔드포인트에서 사용되는 파라미터를 구분해 타입 안정성을 강화할 때
  • 불변하는 값(ID 등) 구분 : 고유한 ID 값과 같이 불변하는 데이터를 명확하게 구분하고자 할 때

다음과 같은 상황에서 적절히 활용할 경우 값을 명확하게 구분할 수 있어 가독성을 높일 수 있지만, 타입 단언에서 비롯된 예상치 못한 런타임 에러나 추가적인 코드가 더 필요할 수 있으므로 남용하지 않는 것이 중요하다

profile
감자

4개의 댓글

comment-user-thumbnail
2024년 7월 3일

컴파일 단계에서만 영향을 미쳐, 컴파일러에게 명시적으로 알리는 역할
런타임 단계에서 아무런 영향을 미치지 않아, 타입 단언을 통해 발생하는 에러는 런타임 에러로 발생한다.
타입스크립트보다 내가 타입을 명확하게 알고 있을 때만 활용한다고 생각하면된다.

혹시 아래의 내용이 맞나요?
"컴파일 단계에서 아무런 영향을 미치지 않아, 타입 단언을 통해 발생하는 에러는 런타임 에러로 발생한다."
(타입을 단언하여 컴파일 단계의 타입 검사를 받지 않는다.)

1개의 답글

관련 채용 정보