요약

내용

  • 여러 인터페이스를 하나의 유니온 타입으로 결합하는 것보다, 인터페이스가 유니온 타입을 가지도록 하는 것이 더 유연하고 확장 가능하다
  1. 유니온 타입의 인터페이스 사용
interface Circle {
  kind: "circle";
  radius: number;
}
 
interface Square {
  kind: "square";
  sideLength: number;
}
 
type Shape = Circle | Square;
 
function getArea(shape: Shape): number {
  if (shape.kind === "circle") {
    return Math.PI * shape.radius ** 2;
  } else if (shape.kind === "square") {
    return shape.sideLength ** 2;
  } else {
    const _exhaustiveCheck: never = shape;
    throw new Error(`Unknown shape: ${_exhaustiveCheck}`);
  }
}
  1. 인터페이스의 유니온 타입 사용
interface Circle {
  radius: number;
}
 
interface Square {
  sideLength: number;
}
 
interface Shape {
  kind: "circle" | "square";
  shape: Circle | Square;
}
 
function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * (shape.shape as Circle).radius ** 2;
    case "square":
      return (shape.shape as Square).sideLength ** 2;
    default:
      const _exhaustiveCheck: never = shape;
      throw new Error(`Unknown shape: ${_exhaustiveCheck}`);
  }
}
  • 타입 안전성: 인터페이스의 유니온 타입을 사용하면, kind 속성에 의해 타입이 좁혀지기 때문에 타입가드를 사용하는 경우보다 코드가 안전하다.
  • 확장성: 새로운 타입을 추가할 때 더 유연하다.
  • 명확성: 코드가 명확하고 각 타입별로 속성을 쉽게 확인 할 수 있다.

  • 새로운 타입 Rectangle을 추가하는 경우…
interface Circle {
  radius: number;
}
 
interface Square {
  sideLength: number;
}
 
interface Rectangle {
  width: number;
  height: number;
}
 
interface Shape {
  kind: "circle" | "square" | "rectangle";
  shape: Circle | Square | Rectangle;
}
 
function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * (shape.shape as Circle).radius ** 2;
    case "square":
      return (shape.shape as Square).sideLength ** 2;
    case "rectangle":
      return (shape.shape as Rectangle).width * (shape.shape as Rectangle).height;
    default:
      const _exhaustiveCheck: never = shape;
      throw new Error(`Unknown shape: ${_exhaustiveCheck}`);
  }
}

참고

  • 이펙티브 타입스크립트