Frontend/Typescript

[μš°μ•„ν•œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ] 4μž₯

μ§€μˆ­μˆ­μˆ­ 2025. 5. 23. 12:47

πŸ“ νƒ€μž… ν™•μž₯ν•˜κΈ°

νƒ€μž… ν™•μž₯은 κΈ°μ‘΄ νƒ€μž…μ„ μ‚¬μš©ν•΄ μƒˆλ‘œμš΄ νƒ€μž…μ„ μ •μ˜ν•˜λŠ” 것을 λ§ν•œλ‹€.

기본적으둜 interface와 type ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ νƒ€μž…μ„ μ •μ˜ν•˜κ³  extends, ꡐ차 νƒ€μž…, μœ λ‹ˆμ˜¨ νƒ€μž…μ„ μ‚¬μš©ν•΄ νƒ€μž…μ„ ν™•μž₯ν•œλ‹€.

 

νƒ€μž… ν™•μž₯의 μž₯점

νƒ€μž… ν™•μž₯의 큰 μž₯점은 μ½”λ“œ 쀑볡을 쀄일 수 μžˆλ‹€λŠ” 것이닀.

μ€‘λ³΅λ˜λŠ” νƒ€μž…μ„ 반볡적으둜 μ„ μ–Έν•˜λŠ” 것보닀 기쑴에 μž‘μ„±ν•œ νƒ€μž…μ„ λ°”νƒ•μœΌλ‘œ νƒ€μž… ν™•μž₯을 ν•¨μœΌλ‘œμ¨ λΆˆν•„μš”ν•œ μ½”λ“œ 쀑볡을 쀄일 수 μžˆλ‹€.

type BaseMenuItem = {
  itemName: string | nill;
  itemImageUrl: string | null;
  itemDiscountAmount: number;
  stock: number | null;
};

type BaseCartItem = {
  quantity: number;
} & BaseMenuItem;

 

μœ λ‹ˆμ˜¨ νƒ€μž…

μœ λ‹ˆμ˜¨ νƒ€μž…μ€ 2개 μ΄μƒμ˜ νƒ€μž…μ„ μ‘°ν•©ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 방법이닀.

type MyUnion = A | B;

A와 B의 μœ λ‹ˆμ˜¨ νƒ€μž…μΈ MyUnion은 νƒ€μž… A와 B의 합집합이닀.

μ§‘ν•© A의 λͺ¨λ“  μ›μ†Œ, μ§‘ν•© B의 λͺ¨λ“  μ›μ†ŒλŠ” μ§‘ν•© MyUnion의 μ›μ†Œμ΄λ‹€.

μœ λ‹ˆμ˜¨ νƒ€μž…μœΌλ‘œ μ„ μ–Έλœ 값은 μœ λ‹ˆμ˜¨ νƒ€μž…μ— ν¬ν•¨λœ λͺ¨λ“  νƒ€μž…μ΄ κ³΅ν†΅μœΌλ‘œ κ°–κ³  μžˆλŠ” μ†μ„±μ—λ§Œ μ ‘κ·Όν•  수 μžˆλ‹€.

 

ꡐ차 νƒ€μž…

ꡐ차 νƒ€μž…μ€ κΈ°μ‘΄ νƒ€μž…μ„ 합쳐 ν•„μš”ν•œ λͺ¨λ“  κΈ°λŠ₯을 κ°€μ§„ ν•˜λ‚˜μ˜ νƒ€μž…μ„ λ§Œλ“œλŠ” κ²ƒμœΌλ‘œ 이해할 수 μžˆλ‹€.

interface CookingStep {
  orderId: string;
  time: number;
  price: number;
}

interface DeliveryStep {
  orderId: string;
  time: number;
  distance: string;
}

type BaedalProgress = CookingStep & DeliveryStep;

BaedalProgressλŠ” CookingStepκ³Ό DeliveryStep νƒ€μž…μ„ 합쳐 λͺ¨λ“  속성을 κ°€μ§„ 단일 νƒ€μž…μ΄ λœλ‹€.

 

type MyIntersection = A & B;

ꡐ차 νƒ€μž…μ€ κ΅μ§‘ν•©μ˜ κ°œλ…κ³Ό λΉ„μŠ·ν•˜λ‹€.

MyIntersection νƒ€μž…μ˜ λͺ¨λ“  값은 Aνƒ€μž…κ³Ό B νƒ€μž…μ˜ 값이닀.

 

extends와 ꡐ차 νƒ€μž…

type BaseMenuItem {
  itemName: string | null;
  itemImageUrl: string | null;
  itemDiscountAmount: number;
  stock: number | null;
};

type BaseCartItem {
  quantity: number;
} & BaseMenuItem;

const baseCartItem: BaseCartItem = {
  itemName: "떑볢이",
  itemImageUrl: "https://www.wowoo/fwfw.png",
  itemDiscountAmount: 200,
  stck: 100,
  quantity: 2,
};

 

 

BaseCartItem은 quantityλΌλŠ” μƒˆλ‘œμš΄ 속성과 BaseMenuItem의 λͺ¨λ“  속성을 κ°€μ§„ 단일 νƒ€μž…μ΄λ‹€.

μœ λ‹ˆμ˜¨ νƒ€μž…κ³Ό ꡐ차 νƒ€μž…μ„ μ‚¬μš©ν•œ μƒˆλ‘œμš΄ νƒ€μž…μ€ 였직 type으둜만 μ„ μ–Έν•  수 μžˆλ‹€.

 

 

πŸ›‘οΈ νƒ€μž… 쒁히기 - νƒ€μž… κ°€λ“œ

 

νƒ€μž… κ°€λ“œμ— 따라 λΆ„κΈ° μ²˜λ¦¬ν•˜κΈ°

νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ λΆ„κΈ° μ²˜λ¦¬λŠ” 쑰건문과 νƒ€μž… κ°€λ“œλ₯Ό ν™œμš©ν•˜μ—¬ λ³€μˆ˜λ‚˜ ν‘œν˜„μ‹μ˜ νƒ€μž… λ²”μœ„λ₯Ό μ’ν˜€ λ‹€μ–‘ν•œ 상황에 따라 λ‹€λ₯Έ λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” 것을 λ§ν•œλ‹€.

νƒ€μž… κ°€λ“œλŠ” λŸ°νƒ€μž„μ— 쑰건문을 μ‚¬μš©ν•΄ νƒ€μž…μ„ κ²€μ‚¬ν•˜κ³  νƒ€μž… λ²”μœ„λ₯Ό μ’ν˜€μ£ΌλŠ” κΈ°λŠ₯을 λ§ν•œλ‹€.

 

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ 개발 μ‹œ μ—¬λŸ¬ νƒ€μž…μ„ ν• λ‹Ήν•  수 μžˆλŠ” μŠ€μ½”ν”„μ—μ„œ νŠΉμ • νƒ€μž…μ„ 쑰건으둜 λ§Œλ“€μ–΄ λΆ„κΈ° μ²˜λ¦¬ν•˜κ³  싢을 λ•Œκ°€ μžˆλ‹€.

μ—¬λŸ¬ νƒ€μž…μ„ ν• λ‹Ήν•  수 μžˆλ‹€λŠ” 것은 λ³€μˆ˜κ°€ μœ λ‹ˆμ˜¨ νƒ€μž… λ˜λŠ” any νƒ€μž… λ“± μ—¬λŸ¬ νƒ€μž…μ„ 받을 수 μžˆλ‹€λŠ” 것을 λ§ν•˜λŠ”λ° 쑰건으둜 κ²€μ‚¬ν•˜λ €λŠ” νƒ€μž…λ³΄λ‹€ 넓은 λ²”μœ„λ₯Ό κ°–κ³  μžˆλ‹€.

μŠ€μ½”ν”„
νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ μŠ€μ½”ν”„λŠ” λ³€μˆ˜μ™€ ν•¨μˆ˜ λ“±μ˜ μ‹λ³„μžκ°€ μœ νš¨ν•œ λ²”μœ„λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
즉, λ³€μˆ˜μ™€ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜κ±°λ‚˜ μ‚¬μš©ν•  수 μžˆλŠ” μ˜μ—­μ„ λ§ν•œλ‹€.

 

νƒ€μž… κ°€λ“œλŠ” 크게 μžλ°”μŠ€ν¬λ¦½νŠΈ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œ νƒ€μž… κ°€λ“œμ™€ μ‚¬μš©μž μ •μ˜ νƒ€μž… κ°€λ“œλ‘œ ꡬ뢄 κ°€λŠ₯ν•˜λ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈ μ—°μ‚°μžλ₯Ό ν™œμš©ν•œ νƒ€μž… κ°€λ“œλŠ” typeof, instanceof, inκ³Ό 같은 μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•΄ μ œμ–΄λ¬ΈμœΌλ‘œ νŠΉμ • νƒ€μž… 값을 κ°€μ§ˆ μˆ˜λ°–μ— μ—†λŠ” 상황을 μœ λ„ν•˜μ—¬ μžμ—°μŠ€λŸ½κ²Œ νƒ€μž…μ„ μ’νžˆλŠ” 방식이닀.

μžλ°”μŠ€ν¬λ¦½νŠΈ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” λŸ°νƒ€μž„μ— μœ νš¨ν•œ νƒ€μž… κ°€λ“œλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œλ‹€.

 

μ‚¬μš©μž μ •μ˜ νƒ€μž… κ°€λ“œλŠ” μ‚¬μš©μžκ°€ 직접 μ–΄λ–€ νƒ€μž…μœΌλ‘œ 값을 μ’νžμ§€λ₯Ό 직접 μ§€μ •ν•˜λŠ” 방식이닀.

 

μ›μ‹œ νƒ€μž…μ„ μΆ”λ‘ ν•  λ•Œ: typeof μ—°μ‚°μž ν™œμš©ν•˜κΈ°

typeof μ—°μ‚°μžλ₯Ό ν™œμš©ν•˜λ©΄ μ›μ‹œ νƒ€μž…μ— λŒ€ν•΄ μΆ”λ‘ ν•  수 μžˆλ‹€. typeof A === Bλ₯Ό 쑰건으둜 λΆ„κΈ° μ²˜λ¦¬ν•˜λ©΄, ν•΄λ‹Ή λΆ„κΈ° λ‚΄μ—μ„œλŠ” A의 νƒ€μž…μ΄ B둜 μΆ”λ‘ λœλ‹€.

typeof μ—°μ‚°μžλŠ” 주둜 μ›μ‹œ νƒ€μž…μ„ μ’νžˆλŠ” μš©λ„λ‘œλ§Œ μ‚¬μš©ν•  것을 ꢌμž₯ν•œλ‹€.

- string, number, boolean, undefined, object, function, bigint, symbol

const replaceHyphen: (date: string | Date) => string | Date = (date) => {
  if (typeof date === "string") {
    // 이 λΆ„κΈ°μ—μ„œλŠ” date의 νƒ€μž…μ΄ string으둜 μΆ”λ‘ λœλ‹€
  	return date.replace(/-/g, "/");
  }
  
  return date;
};

 

μΈμŠ€ν„΄μŠ€ν™”λœ 객체 νƒ€μž…μ„ νŒλ³„ν•  λ•Œ: instanceof μ—°μ‚°μž ν™œμš©ν•˜κΈ°

instanceof μ—°μ‚°μžλŠ” μΈμŠ€ν„΄μŠ€ν™”λœ 객체 νƒ€μž…μ„ νŒλ³„ν•˜λŠ” νƒ€μž… κ°€λ“œλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

A instanceof B ν˜•νƒœλ‘œ μ‚¬μš©ν•˜λ©° Aμ—λŠ” νƒ€μž…μ„ 검사할 λŒ€μƒ λ³€μˆ˜, Bμ—λŠ” νŠΉμ • 객체의 μƒμ„±μžκ°€ λ“€μ–΄κ°„λ‹€.

instanceofλŠ” A의 ν”„λ‘œν† νƒ€μž… 체인에 μƒμ„±μž Bκ°€ μ‘΄μž¬ν•˜λŠ”μ§€λ₯Ό 검사해 μ‘΄μž¬ν•œλ‹€λ©΄ true, κ·Έλ ‡μ§€ μ•Šλ‹€λ©΄ falseλ₯Ό λ°˜ν™˜ν•œλ‹€.

 

객체의 속성이 μžˆλŠ”μ§€ μ—†λŠ”μ§€μ— λ”°λ₯Έ ꡬ뢄: in μ—°μ‚°μž ν™œμš©ν•˜κΈ°

in μ—°μ‚°μžλŠ” 객체에 속성이 μžˆλŠ”μ§€ ν™•μΈν•œ λ‹€μŒμ— trueλ‚˜ falseλ₯Ό λ°˜ν™˜ν•œλ‹€.

in μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜λ©΄ 속성이 μžˆλŠ”μ§€ μ—†λŠ”μ§€μ— 따라 객체 νƒ€μž…μ„ ꡬ뢄할 수 μžˆλ‹€.

in μ—°μ‚°μžλŠ” A in B의 ν˜•νƒœλ‘œ μ‚¬μš©ν•˜λŠ”λ° 이름 κ·ΈλŒ€λ‘œ AλΌλŠ” 속성이 B 객체에 μ‘΄μž¬ν•˜λŠ”μ§€λ₯Ό κ²€μ‚¬ν•œλ‹€.

 

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ in μ—°μ‚°μžλŠ” λŸ°νƒ€μž„μ˜ κ°’λ§Œμ„ κ²€μ‚¬ν•˜μ§€λ§Œ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” 객체 νƒ€μž…μ— 속성이 μ‘΄μž¬ν•˜λŠ”μ§€λ₯Ό κ²€μ‚¬ν•œλ‹€.

μ—¬λŸ¬ 객체 νƒ€μž…μ„ μœ λ‹ˆμ˜¨ νƒ€μž…μœΌλ‘œ κ°€μ§€κ³  μžˆμ„ λ•Œ in μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•΄ μ†μ„±μ˜ μœ λ¬΄μ— 따라 쑰건 λΆ„κΈ°λ₯Ό ν•  수 μžˆλ‹€.

 

is μ—°μ‚°μžλ‘œ μ‚¬μš©μž μ •μ˜ νƒ€μž… κ°€λ“œ λ§Œλ“€μ–΄ ν™œμš©ν•˜κΈ°

직접 νƒ€μž„ κ°€λ“œ ν•¨μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆλŠ”λ° 이런 λ°©μ‹μ˜ νƒ€μž… κ°€λ“œλŠ” λ°˜ν™˜ νƒ€μž…μ΄ νƒ€μž… λͺ…μ œμΈ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.

νƒ€μž… λͺ…μ œλŠ” A is B ν˜•μ‹μœΌλ‘œ μž‘μ„±ν•˜λ©΄ λ˜λŠ”λ° μ—¬κΈ°μ„œ AλŠ” λ§€κ°œλ³€μˆ˜ 이름이고 BλŠ” νƒ€μž…μ΄λ‹€.

νƒ€μž… λͺ…μ œ
νƒ€μž… λͺ…μ œλŠ” ν•¨μˆ˜μ˜ λ°˜ν™˜ νƒ€μž…μ— λŒ€ν•œ νƒ€μž… κ°€λ“œλ₯Ό μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” νŠΉλ³„ν•œ ν˜•νƒœμ˜ ν•¨μˆ˜μ΄λ‹€.

 

 

🀩 νƒ€μž… 쒁히기 - 식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨

νƒœκ·Έ 된 μœ λ‹ˆμ˜¨μœΌλ‘œλ„ λΆˆλ¦¬λŠ” 식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨μ€ νƒ€μž… μ’νžˆκΈ°μ— 널리 μ‚¬μš©λ˜λŠ” 방식이닀.

 

μ—λŸ¬ μ •μ˜ν•˜κΈ°

type ErrorFeedbackType = TextError | ToastError | AlertError;
const errorArr: ErrorFeedbackType[] = [
  { errorCode: "100", errorMessage: "ν…μŠ€νŠΈ μ—λŸ¬" },
  { errorCode: "200", errorMessage: "ν† μŠ€νŠΈ μ—λŸ¬", toastShowDuration: 3000 },
  { errorCode: "300", errorMessage: "μ–ΌλŸΏ μ—λŸ¬", onConfirm: () => {} },
};

 

식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨

μ—λŸ¬ νƒ€μž…μ„ ꡬ뢄할 방법이 ν•„μš”ν•˜λ‹€. 각 νƒ€μž…μ΄ λΉ„μŠ·ν•œ ꡬ쑰λ₯Ό κ°€μ§€μ§€λ§Œ μ„œλ‘œ ν˜Έν™˜λ˜μ§€ μ•Šλ„λ‘ λ§Œλ“€μ–΄μ£ΌκΈ° μœ„ν•΄μ„œλŠ” νƒ€μž…λ“€μ΄ μ„œλ‘œ 포함 관계λ₯Ό κ°€μ§€μ§€ μ•Šλ„λ‘ μ •μ˜ν•΄μ•Ό ν•œλ‹€.

식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨μ΄λž€ νƒ€μž… κ°„μ˜ ꡬ쑰 ν˜Έν™˜μ„ 막기 μœ„ν•΄ νƒ€μž…λ§ˆλ‹€ ꡬ뢄할 수 μžˆλŠ” νŒλ³„μžλ₯Ό 달아주어 포함 관계λ₯Ό μ œκ±°ν•˜λŠ” 것이닀.

 

식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨μ˜ νŒλ³„μž μ„ μ •

식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨μ„ μ‚¬μš©ν•  λ•Œ μ£Όμ˜ν•  점이 μžˆλ‹€.

식별할 수 μžˆλŠ” μœ λ‹ˆμ˜¨μ˜ νŒλ³„μžλŠ” μœ λ‹› νƒ€μž…μœΌλ‘œ μ„ μ–Έλ˜μ–΄μ•Ό μ •μƒμ μœΌλ‘œ λ™μž‘ν•œλ‹€.

μœ λ‹› νƒ€μž…μ€ λ‹€λ₯Έ νƒ€μž…μœΌλ‘œ μͺΌκ°œμ§€μ§€ μ•Šκ³  였직 ν•˜λ‚˜μ˜ μ •ν™•ν•œ 값을 κ°€μ§€λŠ” νƒ€μž…μ„ λ§ν•œλ‹€.

null, undefined, λ¦¬ν„°λŸ΄ νƒ€μž…μ„ λΉ„λ‘―ν•΄ true, 1 λ“± μ •ν™•ν•œ 값을 λ‚˜νƒ€λ‚΄λŠ” νƒ€μž…μ΄ μœ λ‹› νƒ€μž…μ— ν•΄λ‹Ήν•œλ‹€.

void, string, number와 같은 νƒ€μž…μ€ μœ λ‹› νƒ€μž…μœΌλ‘œ μ μš©λ˜μ§€ μ•ŠλŠ”λ‹€.

 

 

✨ Exhaustiveness Checking으둜 μ •ν™•ν•œ νƒ€μž… λΆ„κΈ° μœ μ§€ν•˜κΈ°

Exhausitiveness Checking은 λͺ¨λ“  μΌ€μ΄μŠ€μ— λŒ€ν•΄ μ² μ €ν•˜κ²Œ νƒ€μž…μ„ κ²€μ‚¬ν•˜λŠ” 것을 λ§ν•˜λ©° νƒ€μž… μ’νžˆκΈ°μ— μ‚¬μš©λ˜λŠ” νŒ¨λŸ¬λ‹€μž„ 쀑 ν•˜λ‚˜λ‹€.

νƒ€μž… κ°€λ“œλ₯Ό μ‚¬μš©ν•΄ νƒ€μž…μ— λŒ€ν•œ λΆ„κΈ° 처리λ₯Ό μˆ˜ν–‰ν•˜λ©΄ ν•„μš”ν•˜λ‹€κ³  μƒκ°λ˜λŠ” λΆ€λΆ„λ§Œ λΆ„κΈ° 처리λ₯Ό ν•˜μ—¬ μš”κ΅¬ 사항에 λ§žλŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•  수 있게 λœλ‹€.

 

type ProductPrice = "10000" | "20000" | "5000";

const getProductName = (productPrice: ProductPrice): string => {
  if (productPrice === "10000") return "λ°°λ―Όμƒν’ˆκΆŒ 1만 원";
  if (productPrice === "20000") return "λ°°λ―Όμƒν’ˆκΆŒ 2만 원";
  // if (productPrice === "5000") return "λ°°λ―Όμƒν’ˆκΆŒ 5천 원";
  else {
    exhaustiveCheck(productPrice); // Error: Argument of type 'string' is not assignable to parameter of type 'never'
    return "λ°°λ―Όμƒν’ˆκΆŒ";
  }
};

cosnt exhaustiveCheck = (param: never) => {
  throw new Error("type error!");
};

μœ„ μ½”λ“œμ—μ„œμ²˜λŸΌ λͺ¨λ“  μΌ€μ΄μŠ€μ— λŒ€ν•œ λΆ„κΈ° 처리λ₯Ό ν•΄μ£Όμ§€ μ•Šμ•˜μ„ λ•Œ, μ»΄νŒŒμΌνƒ€μž„ μ—λŸ¬κ°€ λ°œμƒν•˜κ²Œ λ˜λŠ” 것을 Exhaustiveness Checking이라고 ν•œλ‹€.

 

 

728x90