이전 포스팅을 쓰다가 브랜드 타입
에 대해 알게 되어서 간략하게 정리해본다.
type Brand<K, T> = K & {__brand: T}
/**
* 브랜드 타입을 사용하지 않았을 때
*/
// number 타입의 두 변수를 선언한다
const euro1 = 1;
const won1 = 2;
const euroToUsd = (euro: number) => {
return euro * 10;
}
const wonToUsd = (won: number) => {
return won * 20;
}
euroToUsd(won1); // OK
wonToUsd(euro1); // OK
// ==> euro를 인자로 받는 함수에 won을 넘겨도 에러가 발생하지 않는다. 반대의 경우도 마찬가지이다.
/**
* 브랜드 타입 사용
*/
type Brand<K, T> = K & {__brand: T}; // 브랜딩 타입 정의 : __brand 속성을 추가해준다.
type Euro = Brand<number, 'Euro'>;
type Won = Brand<number, 'Won'>;
const brandEuroToUsd = (euro: Euro) => {
return euro * 10;
}
const brandWonToUsd = (won: Won) => {
return won * 20;
}
const euro2 = 10 as Euro;
const won2 = 20 as Won;
brandEuroToUsd(won2); // ERROR : Argument of type 'Won' is not assignable to parameter of type 'Euro'
brandWonToUsd(euro2); // ERROR : Argument of type 'Euro' is not assignable to parameter of type 'Won'.
// ==> euro를 인자로 받는 함수에 won을 넘기면 에러가 발생한다.
// ==> 같은 number 타입을 인자롤 받더라도 타입을 구분하여 사용할 수 있다.
brandEuroToUsd(euro2); // OK
brandWonToUsd(won2); // OK
type Brand<K, T> = K & {__brand: T};
type Food = Brand<{
protein: number;
carbon: number;
fat: number;
}, 'Food'>
// 브랜드 타입을 인자로 받는 함수
function calculateCalories(food: Food) {
return food.protein * 4 + food.carbon * 4 + food.fat * 9;
}
/**
* 에러가 발생하는 경우
*/
// 1) 브랜드 타입 정의 시 사용한 객체의 프로퍼티만 작성했을 때
const food1 = {
protein: 10,
carbon: 10,
fat: 10
}
calculateCalories(food1); // ERROR
// 2) 변수 타입을 지정해줬을 때
const food2: Food = {
protein: 15,
carbon: 15,
fat: 15
}
calculateCalories(food2); // ERROR(변수 선언부터 이미 에러)
/**
* 정상 동작하는 경우
*/
// 3) 타입 단언해줬을 때
const food3 = {
protein: 20,
carbon: 20,
fat: 20
} as Food
calculateCalories(food3); // OK
// 4) 브랜드 직접 지정해줬을 때
const food4: Food = {
protein: 20,
carbon: 20,
fat: 20,
__brand: 'Food'
}
calculateCalories(food4); // OK