typescript

Passing yet-unknown types to instances of generic class objects


I've got a generic class:


export class EdocReport<TtypeDTO, TTypeFinalObject> {
  constructor(
    private _address: string,
    private _queryKey: QueryKey,
    private _sort: "NONE" | keyof TtypeDTO | ((dataArray: TtypeDTO) => TtypeDTO)
  ) {
    this._address = _address;
    this._queryKey = _queryKey;
    this._sort = _sort;
  }

//logic to convert/map from type TtypeDTO into TTypeFinalObject

}

I want to use object instances of that class in custom hook that will look like:

export const useGetEdocReports = (edocReportsData: TEdocReportsData) => {
//fetching data / sorting / mapping ... whatever 
}

The incoming argument data type is to be:

type TEdocReportsData = {
  token: string;
  setIsLoading: (boolValue: boolean) => void;
  reports: EdocReport[];
};

Here the problem occurs. I want to pass an array of reports (instances of EdocReport class), all of them will have different pairs of DTO type and finalObject type, but TypeScript reports that:

Generic type 'EdocReport<TtypeDTO, TTypeFinalObject>' requires 2 type argument(s).

As if I would have to make declaration in advance and specify what the type TtypeDTO and TTypeFinalObject will be.

I wish to finally use the hook like this:

useGetEdocReports({
  token: "token",
  setIsLoading: (boolValue: boolean) => setIsCustomLoading(boolValue),
  reports: [
    new EdocReport<DTOtype1, Type1>({...required_data}),
    new EdocReport<DTOtype2, Type2>({...required_data2}),
    new EdocReport<DTOtype3, Type3>({...required_data3})
  ]
})

Solution

  • Just feed your type with <any, any>.

    You could also use const so TS could infer exact types provided in the report array if needed for some usage.

    Playground

    export class EdocReport<TtypeDTO, TTypeFinalObject> {
    }
    
    export const useGetEdocReports = <const D extends TEdocReportsData>(edocReportsData: D) => {
        return edocReportsData;
    }
    
    type TEdocReportsData = {
      token: string;
      setIsLoading: (boolValue: boolean) => void;
      reports: EdocReport<any, any>[]
    }
    
    const reports = useGetEdocReports({
      token: "token",
      setIsLoading: (boolValue: boolean) => setIsCustomLoading(boolValue),
      reports: [
        new EdocReport<Number, Date>(),
        new EdocReport<Date, string>(),
        new EdocReport<number, boolean>()
      ]
    })
    
    /*
    const reports: {
        readonly token: "token";
        readonly setIsLoading: (boolValue: boolean) => any;
        readonly reports: [EdocReport<Number, Date>, EdocReport<Date, string>, EdocReport<...>];
    }
    */