카테고리 없음

[TS] 대수자료구조에서(ADT) 에서 태그유니언을 사용하기

0hyeon의 2023. 9. 21. 11:13
반응형

 

값의 유무를 명시적으로 다루기위해,  타입스크립트와 같은 *정적인 타입 언어에서는 값의 유무를 명확하게 다루는것이 중요합니다.  이는 데이터가 갑자기 undifined | null 과 같은경우에도 타입추론이 가능해야하며 값을 명시적으로 표기하여야하는 타입스크립트의 정적인 타입언어의 특성을 따르기도 합니다. 

export type Some<A> = {
  _tag: "Some";
  value: A;
};
export type None = {
  _tag: "None";
};

export type Option<A> = Some<A> | None;

const n1: Option<number> = { _tag: "Some", value: 1 };

export const some = <A>(value: A): Option<A> => ({ _tag: "Some", value });
export const none = (): None => ({ _tag: "None" });

export const isSome = <A>(oa: Option<A>): oa is Some<A> => oa._tag === "Some";
export const isNone = <A>(oa: Option<A>): oa is None => oa._tag === "None";

 

이렇게 타입을 정하는 이유는 값의 부재를 선택적인 속성을 처리하고 

값의 부재를 명시적으로 다루기 위함입니다. 해당코드는 아래코드에서 사용이 될텐데요,

 

export const fromUndefined = <A>(a: A | undefined): Option<A> => {
  if (a === undefined) return none();
  return some(a);
};

export const getOrElse = <A>(oa: Option<A>, defaultValue: A): A => {
  if (isNone(oa)) return defaultValue;
  return oa.value;
};

export const map = <A, B>(oa: Option<A>, f: (a: A) => B): Option<B> => {
  if (isNone(oa)) return oa;
  return some(f(oa.value));
};


값이 존재하면 Some으로 감싸고 부재하면 None을 반환하거나,
예상치 못한 undefined | null로 인한 오류를 방지하고 default값을 반환하여 안전하게 접근합니다.

ex) getOrElse(optionDiscountPrice, 0) 

 

해당 코드들의 활용은 다음과 같습니다.

 

const stockItem = (item: Item): string => {
  const optionDiscountPrice = O.fromUndefined(item.discountPrice); //값의부재를파악 some(a) | none을 반환
  const discountPrice = O.getOrElse(optionDiscountPrice, 0); //값이없다면 default값
  let saleText = "";
  // let discountPrice = 0;
  if (O.isSome(optionDiscountPrice)) {
    //응용해서 다른값을 만들기 때문에 getOrElse로 구현 할수없다.
    saleText = `${optionDiscountPrice}원 할인`;
  }
  return `
        <li>
            <h2>${item.name}</h2>
            <div>가격: ${item.price - discountPrice}원 ${saleText}</div>
            <div>수량: ${item.quantity}</div>
        </li>
    `;
};
const outOfStockItem = (item: Item): string => `
    <li class="gray">
        <h2>${item.name} (품절)</h2>
        <div class="strike">가격: ${item.price}원</div>
        <div class="strike">수량 : ${item.quantity}상자</div>
    </li>
`;

이런식으로, 

let saleText = "";
let discountPrice = 0;
if (item.discountPrice !== undefined) {
    saleText = `${item.discountPrice}원 할인`;
    discountPrice = item.discountPrice;
}

 

바로 위에 코드를 사용하는 대신 값이 undfined일경우 값의 부재를 명시적으로 다루고, 

보다 안전하게 접근할수 있도록 할수 있습니다.

 

 

 

 

(참고)

*정적 타입 언어(Static Typing Language)
정적 타입 언어는 변수의 데이터 타입을 컴파일 시간에 결정하며, 코드 작성 시에 변수의 타입을 명시적으로 선언해야 합니다.

특징:
변수의 타입은 명시적으로 선언되므로 코드의 안정성과 가독성이 높아집니다.
컴파일러는 타입 불일치 에러를 미리 감지할 수 있으므로 런타임 오류를 방지합니다.
코드의 예측 가능성이 높아지며, 코드 자동 완성, 리팩토링 도구 등이 타입 정보를 활용하여 도움을 줄 수 있습니다.

예시 언어: TypeScript, Java, C++, C#, Kotlin 등이 정적 타입 언어에 속합니다.


vs 동적타입언어(Dynamic Typing Language)
동적 타입 언어는 변수의 데이터 타입을 런타임 시에 결정하며, 코드 작성 시에 변수의 타입을 명시적으로 선언할 필요가 없습니다.

예시 언어: JavaScript, Python, Ruby, PHP 등이 동적 타입 언어에 속합니다.

특징:

변수의 타입은 실행 시간에 결정되므로 코드 작성이 유연합니다.
런타임 시 타입 불일치 에러가 발생할 수 있으며, 이를 방지하기 위해 명시적인 타입 검사를 추가로 수행해야 할 수 있습니다. 코드가 짧고 간결할 수 있으며, 빠른 개발 및 프로토타이핑에 적합합니다.

 

읽어주셔서 감사합니다 :)

반응형