U
U
user_of_toster2021-05-25 14:12:56
typescript
user_of_toster, 2021-05-25 14:12:56

How to make a factory?

Let's say we have an abstract Figure:

interface FigureData {
  width: number,
}

abstract class Figure<T extends FigureData> {
  constructor(data: T) {};
}

triangle:
interface TriangleData extends FigureData {
  someTriangleProperty: string,
}

class Triangle extends Figure<TriangleData>{
  constructor(data: TriangleData) {
    super(data);
  }
}

circle:
interface CircleData extends FigureData {
  radius: number,
}

class Circle extends Figure<CircleData> {
  constructor(data: CircleData) {super(data)};
}

Now I want the repository to take the shape ID as input and return the shape instance. For this I need a factory:
class FigureFactory<T extends FigureData> {
  create(type: string, data: T) {
    if (type == 'CIRCLE') return new Circle(data)
    else if (type === 'TRIANGLE') return new Triangle(data);
  }
}

However, the compiler does not allow this:
Argument of type 'T' is not assignable to parameter of type 'CircleData'.
Property 'radius' is missing in type 'FigureData' but required in type 'CircleData'.ts(2345)

Question #1 - how to calm down the compiler?
Question #2 - Do I write shitty code and if so, how can I do it better?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ilya, 2021-05-25
@user_of_toster

You don't really guarantee that the type passed to Circle will be CircleData.
In typescript, structural typing. You either need to make sure that the input data structure corresponds to CircleData or enter the type field in FigureData that you will fix in each successor.
And yes, you have bad code, because your inheritance violates the Liskov substitution principle. Moreover, you took a classic example, which usually demonstrates the violation of this principle.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question