#Generic structure with optional overload

5 messages · Page 1 of 1 (latest)

shut kestrel
#

Hello!

I would like to create a CRUD factory for any entity can support return types to be customized

Here is a non-working example of what I would like to attempt:

type ReturnTypes<T, TList = T[], TCreate = T> = {
  List?: TList;
  Create?: TCreate;
};

class MyCRUDFactory<T, TReturnTypes extends ReturnTypes<T> = ReturnTypes<T>> {
  list(): TReturnTypes['List'] {
    // Logic
  }

  create(): TReturnTypes['Create'] {
    // Logic
  }

  // read, update, delete
}

type MyItem = {
  id: string;
  value: string;
};

type MySimplifiedItem = {
  id: string;
};

class MyCRUD extends MyCRUDFactory<MyItem, { List: MySimplifiedItem[] }> {}

const instance = new MyCRUD();

instance.list(); // MySimplifiedItem[]
instance.create(); // MyItem

The problem is that:

  • Type 'MySimplifiedItem[]' is not assignable to type 'MyItem[]'.
  • instance.create(); return unknown

What I would like is to be able to specify any type for each return type "property" of my ReturnTypes type, while keeping default type defined if not overloaded

Is it possible?

silver snow
#

First problem:
The second generic parameter of MyCRUDFactory extends ReturnTypes<T> = ReturnTypes<T, T[], T> = {List?: T[], Create?: T}. Since T is bound to MyItem (line 27), {List: MySimplifiedItem[]} does not satisfy ReturnTypes<T>.
One solution is to specify that TList can be anything:
class MyCRUDFactory<T, TReturnTypes extends ReturnTypes<T, any> = ReturnTypes<T, any>> {

#

Second problem:
I guess that since Create is optional, the return type of create cannot be inferred.

#

Is there a reason you are not just using:

abstract class MyCRUDFactory<T, TList = T[], TCreate = T> {
  abstract list(): TList;
  abstract create(): TCreate;
  // read, update, delete
}
#

or

abstract class MyCRUDFactory<T, TList = T, TCreate = T> {
  abstract list(): TList[];
  abstract create(): TCreate;
  // read, update, delete
}