Gwangju-Web-Study / WoowahanTS_Study

✏️우아한 타입스크립트 with 리액트 스터디
6 stars 2 forks source link

4.1.5 제네릭을 사용해서 배달의 민족 메뉴 시스템 예시처럼 타입확장을 만들어보세요. #16

Closed BaekWeb closed 2 months ago

BaekWeb commented 2 months ago

📝 p 128

❓ 배달의 민족 메뉴 시스템에 타입 확장을 적용한 예시가 있습니다. 3장에서 제네릭을 활용하여 타입의 확장을 적용한 예시를 작성하고 설명 해주세요.

hyeonseong2023 commented 2 months ago
interface Clothes {
  name: string;
  price: number;
}

type SizeWithUnit = `${number}cm`;

interface ClothesWithSize<TSize> extends Clothes {
  size: TSize;
}

// 상의는 S, M, L 중 하나
interface TopClothes extends ClothesWithSize<"S" | "M" | "L"> {
  sleeveSize: SizeWithUnit;
}

// 하의는 숫자
interface BottomsClothes extends ClothesWithSize<number> {
  waistSize: SizeWithUnit;
}

const tShirt: TopClothes = {
  name: "T-Shirt",
  price: 25000,
  size: "L",
  sleeveSize: "25cm",
};

const jeans: BottomsClothes = {
  name: "Jeans",
  price: 40000,
  size: 32,
  waistSize: "34cm",
};

console.log(tShirt); // { name: "T-Shirt", price: 25000, size: "L", sleeveSize: "25cm" }
console.log(jeans);  // { name: "Jeans", price: 40000, size: 32, waistSize: "34cm" }

상의와 하의에서 size라는 속성은 같으나 값이 다른 사이즈 적용법인 경우, 각 객체의 고유의 속성을 보유하는 경우의 예시입니다.

gwangminjun commented 2 months ago
// 제네릭을 사용한 Food 인터페이스 정의
interface Food<T, U extends string | number> {
  name: string;
  calorie: number;
  unit: U; // 단위 타입이 제네릭으로 지정됨
  extra: T; // 제네릭 T를 사용하여 추가 속성 정의
}

// SweetPotato와 Water 타입 정의
type SweetPotato = Food<{ isSweet: boolean }, "g">;
type Water = Food<{ source: string }, "ml">;

// SweetPotato 객체 생성
const sweetPotato: SweetPotato = {
  name: "Sweet Potato",
  calorie: 86,
  unit: "g",
  extra: {
    isSweet: true, // 고구마의 추가 속성: 단맛 여부
  },
};

// Water 객체 생성
const water: Water = {
  name: "Water",
  calorie: 0,
  unit: "ml",
  extra: {
    source: "Spring", // 물의 출처를 나타내는 속성
  },
};

음식이라는 공통된 속성을 공통 인터페이스로 설정하고 해당 속성을 상속받아 확장하는 고구마 , 물 인터페이스 예제 입니다.

BaekWeb commented 2 months ago
interface Transport<T> {
  name: string;   // 교통수단의 이름
  route: string;  // 경로 정보
  time: string;   // 소요 시간 정보
  extraInfo?: T;  // 교통수단에 따라 달라질 수 있는 추가 정보 (제네릭 사용)
}

// Bus 타입을 확장
type BusTransport = Transport<{ busNumber: string }>;

// Taxi 타입을 확장
type TaxiTransport = Transport<{ driverName: string }>;

// Walk 타입을 확장
type WalkTransport = Transport<{ isScenicRoute: boolean }>;

// Bus 리스트
const busTransportList: BusTransport[] = [
  { name: "버스 1", route: "노선 A -> B -> C", time: "30분", extraInfo: { busNumber: "101번" } },
  { name: "버스 2", route: "노선 D -> E -> F", time: "45분", extraInfo: { busNumber: "102번" } },
];

// Taxi 리스트
const taxiTransportList: TaxiTransport[] = [
  { name: "택시 1", route: "출발지 -> 목적지", time: "15분", extraInfo: { driverName: "홍길동" } },
  { name: "택시 2", route: "출발지 -> 목적지", time: "20분", extraInfo: { driverName: "김철수" } },
];

// Walk 리스트
const walkTransportList: WalkTransport[] = [
  { name: "도보 1", route: "길 A -> B", time: "10분", extraInfo: { isScenicRoute: true } },
  { name: "도보 2", route: "길 C -> D", time: "25분", extraInfo: { isScenicRoute: false } },
];