2024-05-29.md

🏑

DIL: μ΄νŽ™ν‹°λΈŒ νƒ€μž…μŠ€ν¬λ¦½νŠΈ

μŠ€ν„°λ””: μ›”κ°„ CS, https://github.com/monthly-cs/2024-05-effective-typescript
μž‘μ„±μΌ: 2024-05-29
μž‘μ„±μž: dusunax


μ•„μ΄ν…œ 32: μœ λ‹ˆμ˜¨μ˜ μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€λŠ” μΈν„°νŽ˜μ΄μŠ€μ˜ μœ λ‹ˆμ˜¨μ„ μ‚¬μš©ν•˜κΈ° Prefer Unions of Interfaces to Interfaces with Unions

Unions of Interfaces & Interfaces with Unions

  • μœ λ‹ˆμ˜¨ νƒ€μž…μ˜ 속성을 κ°€μ§€λŠ” μΈν„°νŽ˜μ΄μŠ€
  • μΈν„°νŽ˜μ΄μŠ€μ˜ μœ λ‹ˆμ˜¨ νƒ€μž…
// πŸ€”
// μœ λ‹ˆμ˜¨μ˜ μΈν„°νŽ˜μ΄μŠ€ Unions of Interfaces
interface User {
  id: string;
  name: string;
  contact: string | number;
}

const user1: User = {
  id: "1",
  name: "Alice",
  contact: "123-456-7890",
};
const user2: User = {
  id: "2",
  name: "Bob",
  contact: 9876543210,
};

// πŸ‘
// μΈν„°νŽ˜μ΄μŠ€μ˜ μœ λ‹ˆμ˜¨ Interfaces with Unions
// νƒ€μž… κ°€λ“œλ₯Ό ν•  수 μžˆλ‹€!
interface Cat {
  type: "cat";
  purrs: boolean;
}

interface Dog {
  type: "dog";
  barks: boolean;
}

type Animal = Cat | Dog;

const animal1: Animal = {
  type: "cat",
  purrs: true,
};

const animal2: Animal = {
  type: "dog",
  barks: true,
};

ꡐ재의 μ˜ˆμ‹œ

  • μœ λ‹ˆμ˜¨μ˜ μΈν„°νŽ˜μ΄μŠ€: λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ 였λ₯˜κ°€ λ°œμƒν•˜κΈ° 쉽고, μΈν„°νŽ˜μ΄μŠ€λ₯Ό 닀루기 μ–΄λ ΅λ‹€
  • λΆ„λ¦¬λœ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μœ λ‹ˆμ˜¨: 잘λͺ»λœ μ‘°ν•©μœΌλ‘œ μ„žμ΄λŠ” 것을 방지
    • νƒœκ·Έ μ‚¬μš©!
    • λŸ°νƒ€μž„μ— νƒ€μž…μ˜ λ²”μœ„λ₯Ό 쒁힐 수 μžˆλ‹€ / νƒ€μž… κ°€λ“œ
// πŸ€”
interface Layer {
  layout: FillLayout | LineLayout | PointLayout;
  paint: FillPaint | LinePaint | PointPaint;
}

// πŸ‘
interface FillLayer {
  layout: FillLayout;
  paint: FillPaint;
}
interface LineLayer {
  layout: LineLayout;
  paint: LinePaint;
}
interface PointLayer {
  layout: PointLayout;
  paint: PointPaint;
}
type Layer = FillLayer | LineLayer | PointLayer;

νƒœκ·Έλœ μœ λ‹ˆμ˜¨ νŒ¨ν„΄

  • μœ μš©ν•œ 경우
    • μΈν„°νŽ˜μ΄μŠ€μ˜ 속성이 μœ λ‹ˆμ˜¨μΈ 경우
    • μ—¬λŸ¬ 개의 선택적 ν•„λ“œκ°€ λ™μ‹œμ— 값이 μžˆκ±°λ‚˜, λ™μ‹œμ— undefined인 경우
  • μž₯점
    • νƒ€μž…μ˜ 속성듀 κ°„ 관계λ₯Ό λͺ¨λΈλ§
    • νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ½”λ“œμ˜ 정확성을 μ²΄ν¬ν•˜λŠ” 데 도움이 λœλ‹€
// πŸ‘Ž
interface Person {
  name: string;
  // νƒ€μž…μ— λŒ€ν•œ 주석은 쒋지 μ•Šλ‹€
  // These will either both be present or not be present
  placeOfBirth?: string; // placeOfBirth와 dateOfBirth의 관계가 ν‘œν˜„λ˜μ§€ μ•Šμ•˜λ‹€
  dateOfBirth?: Date;
}
// πŸ‘
interface Person {
  name: string;
  birth?: {
    place: string; // place와 dateλŠ” ν•¨κ»˜ μ‘΄μž¬ν•œλ‹€
    date: Date;
  };
}

function eulogize(person: Person) {
  console.log(person.name);
  const { birth } = person;
  if (birth) {
    // Person λ§€κ°œλ³€μˆ˜μ—μ„œ birth만 μ²΄ν¬ν•˜λ©΄ λœλ‹€
    console.log(`was born on ${birth.date} in ${birth.place}.`);
  }
}

✨ νƒ€μž…μ˜ ꡬ쑰λ₯Ό 손 댈 수 μ—†λŠ” μ˜ˆμ‹œ: API κ²°κ³Ό

  • μΈν„°νŽ˜μ΄μŠ€λ₯Ό μœ λ‹ˆμ˜¨ν•œ νƒ€μž…μœΌλ‘œ 관계λ₯Ό ν‘œν˜„ν•  수 μžˆλ‹€!~!
interface Name {
  name: string;
}

interface PersonWithBirth extends Name {
  // ν™•μž₯된 interface
  placeOfBirth: string;
  dateOfBirth: Date;
}

type Person = Name | PersonWithBirth; // interface μœ λ‹ˆμ˜¨

// ❗️ μ΄λ ‡κ²Œ μ“Έ 수 μžˆλ‹€!
function eulogize(person: Person) {
  if ("placeOfBirth" in person) {
    // νƒœκ·Έλœ μœ λ‹ˆμ˜¨ 체크
    person;
    // ^? (parameter) person: PersonWithBirth
    const { dateOfBirth } = person; // 정상
    //     ^? const dateOfBirth: Date
  } else {
    // else라면 Name이닀.
    // placeOfBirth와 dateOfBirth을 λ‘˜ λ‹€ 가지고 μžˆμ§€ μ•Šμ€ μΈν„°νŽ˜μ΄μŠ€
  }
}

Things to Remember

  • Interfaces with multiple properties that are union types are often a mistake because they obscure the relationships between these properties.
    • μœ λ‹ˆμ˜¨ νƒ€μž…μ˜ 속성을 μ—¬λŸ¬ 개 κ°€μ§€λŠ” μΈν„°νŽ˜μ΄μŠ€λŠ” 속성 κ°„μ˜ 관계가 λΆ„λͺ…ν•˜μ§€ μ•Šλ‹€.
  • Unions of interfaces are more precise and can be understood by TypeScript.
    • μœ λ‹ˆμ˜¨μ˜ μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€, μΈν„°νŽ˜μ΄μŠ€μ˜ μœ λ‹ˆμ˜¨μ΄ 더 μ •ν™•ν•˜κ³  νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ΄ν•΄ν•˜κΈ° μ’‹λ‹€
  • Use tagged unions to facilitate control flow analysis. Because they are so well supported, this pattern is ubiquitous in TypeScript code.
    • νƒ€μž…μŠ€ν¬λ¦½νŠΈκ°€ μ œμ–΄ 흐름을 뢄석할 수 μžˆλ„λ‘, νƒœκ·Έλ₯Ό λ„£λŠ” 것을 κ³ λ €ν•œλ‹€.
    • νƒœκ·Έλœ μœ λ‹ˆμ˜¨ νŒ¨ν„΄μ€ 자주 μ“°μž„
  • Consider whether multiple optional properties could be grouped to more accurately model your data.
    • μ˜΅μ…”λ„ 속성이 많으면? 그룹을 μ§€μ–΄μ„œ λͺ¨λΈλ§ν•˜λŠ” 것을 κ³ λ €ν•˜κΈ°