변수에 여러 객체 타입 중 하나가 될 수 있는 초깃값이 주어지면 타입스크립트는 해당 타입을 객체 타입 유니언으로 유추함

📍유추된 객체 타입 유니언

변수에 여러 객체 타입 중 하나가 될 수 있는 초깃값이 주어지면 타입스크립트는 해당 타입을 객체 타입 유니언으로 유추함

const poem =
    Math.random() > 0.5
        ? { name: "The Double Image", pages: 7 }
        : { name: "Her Kind", rhymes: true };

poem.name; // ✅ string
poem.pages; // ✅ number | undefined
poem.rhymes; // ✅ booleans | undefined

📍 명시된 객체 타입 유니언

type PoemWithPages = {
  name: string;
  pages: number;
};

type PoemWithRhymes = {
  name: string;
  rhymes: boolean;
};

type Poem = PoemWithPages | PoemWithRhymes;

const poem: Poem =
  Math.random() > 0.5
    ? {
        name: "The Double Image",
        pages: 7,
      }
    : {
        name: "Her Kind",
        rhymes: true,
      };

poem.name; // ✅ ok

poem.pages; // ❌ error
poem.rhymes; // ❌ error

📍 객체 타입 내로잉

if ("pages" in poem) { // 유니언 타입 값에 특정 속성이 포함된 경우에만 코드 영역을 실행할 수 있음을 알게 되면 -> 타입 가드 역할
  poem.pages; // ✅ ok -> 값의 타입을 해당 속성을 포함하는 구성요소로만 좁힘
} else {
  poem.rhymes; // ✅ ok
}

📍 판별된 유니언 (discriminated union)

type PoemWithPages = {
  name: string;
  pages: number;
  type: "pages";
};

type PoemWithRhymes = {
  name: string;
  rhymes: boolean;
  type: "rhymes";
};

type Poem = PoemWithPages | PoemWithRhymes;

const poem: Poem =
  Math.random() > 0.5
    ? {
        name: "The Double Image",
        pages: 7,
        type: "pages",
      }
    : { name: "Her Kind", rhymes: true, type: "rhymes" };

if (poem.type === "pages") { // 판별값
  console.log(`It's got pages: ${poem.pages}`); // ✅ Ok
} else {
  console.log(`It rhymes: ${poem.rhymes}`);
}