24.08.28

강연주·2024년 8월 28일

📚 TIL

목록 보기
35/186
  • type과 interface 공통점, 차이점 정리

[Type vs Interface]

🎀 Interface의 특별한 기능(e.g extends)이 필요할 때를 빼면
기본적으로 type을 사용하라.

https://www.totaltypescript.com/type-vs-interface-which-should-you-use

  • Interface는 union 타입, 맵핑된 타입, 조건부 타입을 나타낼 수 없다.
    Type은 어떤 타입도 표현 가능.

  • Interface는 extends 사용 가능, Type은 불가능.

  • 서로를 상속하는 객체를 다룰 때는 Interface 사용 권장.
    extends가 & 연산자보다 조금 더 빠르다.

  • 동일 스코프 내에서 동명의 Interface 사용은 선언을 병합시키며
    예기치 못한 버그 유발.

  • Type은 Record<PropertyKey, unknown>라는 implicit index signature를 가진다.

⭐ What is implicit indexing?
: An Implicit index (also known as a null-index) is an index that does not have a name, e.g. a list (a 1-dimensional array). It arises in rare cases in a Definition that contains a subexpression that generates a list of values.
(https://docs.analytica.com/index.php/Implicit_index)

공통점

  • Type Alias와 Interface 둘 다
    타입에 대해 유사한 방식으로 이름 짓기 가능
interface Human {
  name: string;
  age: number;
}

const henry: Human = {
  name: '남현욱',
  age: 20,
};

//

type Human = {
  name: string;
  age: number;
};

const henry: Human = {
  name: '남현욱',
  age: 20,
};
  • (제한적으로) 여러 타입에 대한 관계 정의

Type Alias 와 Interface 둘 다, Interface에 대한 extends와 Class에 대한 implements 키워드를 사용하여 관계를 정의할 수 있습니다.
(❓❓❓❓❓)
주의점은 객체 타입이나 객체 타입 간 곱 타입(Intersection Type, 교차 타입),
즉 정적으로 모양을 알 수 있는 객체 타입만 동작합니다.
따라서, 합 타입(Union Type, 결합 타입)은 extends와 implements 대신
다른 키워드로 관계를 정의해야 합니다.

차이점

  • Interface는 선언 병합 가능, Type은 불가능
제목1제목2
내용1입니다내용2입니다
내용1내용2

(https://medium.com/humanscape-tech/type-vs-interface-%EC%96%B8%EC%A0%9C-%EC%96%B4%EB%96%BB%EA%B2%8C-f36499b0de50)


📇 BadgeCards 리팩토링은 계속된다

  • BadgeCards.tsx 로직 supabase 이용 리팩토링

어제 더 나은 방법이라고 제시된 코드이긴 한데,
여전히 condition은 두 종류밖에 없다는 전제 하에 동작하고 있어
확장성이 0에 수렴한다.
실제로 향후 프로젝트의 발전 방향을 놓고 볼 때,
배지 추가와 그에 따른 확장성 증대는 필수불가결이라고 생각하므로
더 고민하기로 한다.

const badgesState = useMemo(() => {
  return totalBadges.map((badgeGroup) => {
    const badge = { ...badgeGroup[1] };
    const matchingCondition = badgeConditions.find((cond) => badge.id.includes(cond.idPart));
    
    const isObtained = matchingCondition
      ? matchingCondition.condition(
          matchingCondition.idPart.includes('다이어리수집가') || matchingCondition.idPart.includes('문구점사장님')
            ? diaryCount
            : membershipDays
        )
      : false;

    badge.isObtained = isObtained;
    badge.content = isObtained ? badge.content.replace('false', 'true') : badge.content.replace('true', 'false');

    return badge;
  });
}, [diaryCount, membershipDays]);

Q : 그럼 이 코드에서 condition 타입의 종류가 2개를 초과할 때는 어떻게 해? 마치 타입 종류가 2개만 있는 것처럼 삼항연산자를 사용하고 있잖아. 확장성이 떨어지지 않아?

A : 맞습니다. 이를 해결하기 위해서는 conditionType에 따라 처리할 값을 선택하는 더 유연한 방법이 필요합니다. 예를 들어, switch 문이나 객체 매핑을 사용하여 확장 가능한 구조로 변경할 수 있습니다.

  • switch문 사용
const badgesState = useMemo(() => {
  return totalBadges.map((badgeGroup) => {
    const badge = { ...badgeGroup[1] };
    const matchingCondition = badgeConditions.find((cond) => badge.id.includes(cond.idPart));

    let valueToCheck;
    switch (matchingCondition?.conditionType) {
      case 'diaryCount':
        valueToCheck = diaryCount;
        break;
      case 'membershipDays':
        valueToCheck = membershipDays;
        break;
      // 추가적인 conditionType에 대해 다른 값을 사용할 수 있습니다.
      default:
        valueToCheck = null; // 만약 conditionType이 정의되지 않았을 경우
    }

    const isObtained = matchingCondition ? matchingCondition.condition(valueToCheck) : false;

    badge.isObtained = isObtained;
    badge.content = isObtained ? badge.content.replace('false', 'true') : badge.content.replace('true', 'false');

    return badge;
  });
}, [diaryCount, membershipDays]);

  • 객체 매핑 사용
const valueMap = {
  diaryCount: diaryCount,
  membershipDays: membershipDays,
  // 다른 conditionType에 대한 값을 추가할 수 있습니다.
};

const badgesState = useMemo(() => {
  return totalBadges.map((badgeGroup) => {
    const badge = { ...badgeGroup[1] };
    const matchingCondition = badgeConditions.find((cond) => badge.id.includes(cond.idPart));

    const valueToCheck = matchingCondition ? valueMap[matchingCondition.conditionType] : null;

    const isObtained = matchingCondition ? matchingCondition.condition(valueToCheck) : false;

    badge.isObtained = isObtained;
    badge.content = isObtained ? badge.content.replace('false', 'true') : badge.content.replace('true', 'false');

    return badge;
  });
}, [diaryCount, membershipDays]);

객체를 사용하여 conditionType과 관련된 값을 매핑.
이렇게 하면 새로운 conditionType이 생겨도,
객체에 추가만 하면 되므로 확장성을 개선할 수 있다.

profile
아무튼, 개발자

0개의 댓글