https://blog.jez.io/intro-elim/

Every type is defined by its intro and elim forms

  • Intro forms: 타입의 인스턴스를 어떻게 “생성”하는지 정의.
  • Elim forms: 생성된 타입 인스턴스를 어떻게 “사용”하거나 “해체”할지 정의.

타입을 정의할 때, 생성과 사용의 명확한 경계를 설정해서 Intro/Elim 설계를 명시적으로 표현하기

class Rectangle {
  private constructor(public width: number, public height: number) {}

  static create(width: number, height: number) {
    if (width <= 0 || height <= 0) {
      return null
    }

    return new Rectangle(width, height)
  }

  getArea() {
    return this.width * this.height
  }
}

const rect = Rectangle.create(10, 20)

if (rect) {
  console.log(rect.getArea())
}

Types are not their elim forms

  • interfaceclass를 통해 Intro/Elim 모두를 명시적으로 정의
  • 팩토리 메서드 같은 패턴을 활용해 생성 방식을 추상화
interface Shape {
  getArea(): number
}

class Circle implements Shape {
  constructor(private radius: number) {}

  getArea() {
    return Math.PI * this.radius ** 2
  }
}

class Rectangle implements Shape {
  constructor(private width: number, private height: number) {}

  getArea() {
    return this.width * this.height
  }
}

function createShape(type: 'circle' | 'rectangle', ...args: number[]) {
  if (type === 'circle' && args.length === 1) {
    return new Circle(args[0])
  }

  if (type === 'rectangle' && args.length === 2) {
    return new Rectangle(args[0], args[1])
  }

  return null
}

const shape = createShape('circle', 10)

if (shape) {
  console.log(shape.getArea())
}
#380