Search code examples
typescriptdynamicabstract-class

return dynamic type in method of abstract class <T> TypeScript


I have my abtract class

export abstract class Filters<P> {
  protected field: string;

  protected constructor(field: string) {
    this.field = field;
  }

  protected abstract getFilter(): P;
}

and one interface

interface IRagne<T> {
  field: string;
  from: T;
  to: T;
}

and my implementation of abstract Filters class

class RangeFilter<T, P = IRagne<T>> extends Filters<P> {
  private from: T;
  private to: T;

  constructor(field: string, from: T, to: T) {
    super(field);
    this.from = from;
    this.to = to;
  }

  getFilter(): P {
    return {
      field: super.field,
      from: this.from,
      to: this.to
    };
  }
}

but my ide show a error in getFilter implementation try with getFilter(): IRange<T> but don't work


Solution

  • Problem here is you try to compute type P in generic types declaration : you can't do this. The equals operator in generic type is used for default value. So, in this declaration class RangeFilter<T, P = IRange<T>>, you basically say RangeFilter class need 2 types to work, and if you don't provide the second one, he will default to IRange<T>, but you can provide what you want for this second type.

    With your declaration, RangeFilter<xxx, string> or RangeFilter<xxx, number> will be perfectly valid, and in these cases, getFilter return value will be wrong.

    Good solution here is the following

    class RangeFilter<T> extends Filters<IRange<T>> {
      private from: T;
      private to: T;
    
      constructor(field: string, from: T, to: T) {
        super(field);
        this.from = from;
        this.to = to;
      }
    
      getFilter(): IRange<T> {
        return {
          field: super.field,
          from: this.from,
          to: this.to
        };
      }
    }