Skip to content

ADTs with inheritance #20144

Closed
Closed
@afroozeh

Description

@afroozeh

I'd like to define an ADT and also enforce that all concrete types implement another interface (I know that is not how ADTs are supposed to be used, but since TypeScript is a mixed paradigm language, I'd like to be able to do it the way I'm used to it in Scala). This is an attempt to achieve it:

type Shape = Circle | Rectangle

interface Drawable {
    draw();
}

class Circle implements Drawable {
    constructor(readonly kind: "circle", readonly radius: number) { }
    draw() {}
}

class Rectangle implements Drawable {
    constructor(readonly kind: "square", readonly weight: number, readonly height: number) { }
    draw() {} 
}

let s: Shape;
s.draw();

The problem is that I cannot enforce that all concrete classes implement Drawable when defining them:

type Shape = Circle | Square | Triangle

// This is ok, since there is no way to enforce Triangle to implement Drawable
class Triangle {
    constructor(readonly kind: "square", readonly side1: number, readonly side2: number, side3: number) { }
}

let s: Shape;
s.draw(); // Error: property draw does not exist on Shape

and I only will get an error when actually call draw() on a Shape instance.

In Scala, for example, I can enforce that all concrete case classes to implement the Drawable interface:

trait Drawable {
  def draw(): Unit
}

trait Shape extends Drawable

case class Circle(radius: Int) extends Shape {
  override def draw() {}
}

case class Square(width: Int, height: Int) extends Shape {
  override def draw() {}
}

// Error: Triangle does not implement draw
case class Triangle(side1: Int, side2: Int, side3: Int) extends Shape {
}

Is there a way to achieve this in TypeScript?
Is there a plan to allow discriminated union type matching feature with interfaces?
Is there a plan to allow type aliases to extend interfaces?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions