반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

인터페이스의 유니온 사용하기 본문

TS/이펙티브 타입스크립트

인터페이스의 유니온 사용하기

5_hyun 2023. 3. 27. 17:58

유니온의 인터페이스보다는 인터페이스의 유니온을 지향하는 것이 좋다. 사실 앞 문장만 딱 보면 좀 헷갈릴 수 있다. 하지만 막상 코드를 보면 익숙할 것이다.

백터를 그리는 프로그램 작성 예제

유니온의 인터페이스

interface Layer {
  layout: FillLayout | LineLayout | PointLayout;
  paint: FillPaint | LinePaint | PointPaint;
}

이 코드는 유니온의 인터페이스이다. layout은 모양이 그려지는 방법, 위치를 제어하고, paint는 선의 스타일을 제어한다. 두 속성은 Fill, Line, Point 3개 중 하나를 통일해서 가져야 한다. 하지만 layout은 FillLayout, paint는 LinePaint로 하면 에러가 나게 될 것이다. 그렇기에 더 나은 모델링을 하기 위해서 각 타입을 계층으로 분리하여 인터페이스로 둬야한다.

인터페이스의 유니온 

interface FillLayer {
  layout: FillLayout
  paint: FillPaint
}
interface LineLayer {
  layout: LineLayout
  paint: LinePaint
}
interface PointLayer {
  layout: PointLayout
  paint: PointPaint
}
type Layer = FillLayer | LineLayer | PointLayer

이렇게 정의하면 조합이 잘못되는 경우를 방지할 수 있다. 이러한 패턴의 일반적인 예시는 태그 된 유니온 기법이다.

 

-태그 된 유니온

interface FillLayer {
  type: 'fill'
  layout: FillLayout
  paint: FillPaint
}
interface LineLayer {
  type: 'line'
  layout: LineLayout
  paint: LinePaint
}
interface PointLayer {
  type: 'paint'
  layout: PointLayout
  paint: PointPaint
}
type Layer = FillLayer | LineLayer | PointLayer

type은 태그이고 런타임에 어떤 타입의 Layer가 사용되는지 판단할 수 있다. TS는 타입을 참고해 타입의 범위를 좁힐 수 있다.

function drawLayer(layer: Layer) {
  if (layer.type === 'fill') {
    const { paint } = layer // Type is FillPaint
    const { layout } = layer // Type is FillLayout
  } else if (layer.type === 'line') {
    const { paint } = layer // Type is LinePaint
    const { layout } = layer // Type is LineLayout
  } else {
    const { paint } = layer // Type is PointPaint
    const { layout } = layer // Type is PointLayout
  }
}

이렇게 타입의 범위를 좁힐 수 있어 태그된 유니온 기법은 유용하다. 태그된 유니온은 타입스크립트 타입 체커와 잘 맞고 이 패턴을 잘 적용할 수 있어야 한다. 어떤 데이터 타입을 태그된 유니온 기법으로 표현할 수 있으면 보통 하는 것이 좋다.

 

-여러 개의 필드가 동시에 있거나 없는 경우

interface Person {
  name: string
  // These will either both be present or not be present
  placeOfBirth?: string
  dateOfBirth?: Date
}

여러 개의 속성이 상황에 따라 모두 있거나 모두 없어야 하면 숙달되지 않은 사람은 위 코드처럼 모델링할 것이다.

interface Person {
  name: string
  birth?: {
    place: string
    date: Date
  }
}

이렇게 여러 개의 속성을 한 객체에 모으는 것이 더 좋은 설계이다.

728x90
반응형
Comments