0
votes

I get an error in TypeScript 2.4.2 on a generic class with a constraint not being compatible with the interface which is less strict. I get the following error:

ts/components/Schedule.ts(37,13): error TS2322: Type '{ personWeekView: PlanItemScheduleView; projectWeekView: PlanItemScheduleView; r...' is not assignable to type 'Map'. Property 'personWeekView' is incompatible with index signature. Type 'PlanItemScheduleView' is not assignable to type 'IPlanItemScheduleView'. Types of property 'onAddedItem' are incompatible. Type '(item: T, initial: boolean) => void' is not assignable to type '(item: T, initial: boolean) => void'. Types of parameters 'item' and 'item' are incompatible. Type 'T' is not assignable to type 'PlanItem'.

ts/views/PlanItemScheduleView.ts(2,18): error TS2420: Class 'PlanItemScheduleView' incorrectly implements interface 'IPlanItemScheduleView'. Types of property 'onAddedItem' are incompatible. Type '(item: T, initial: boolean) => void' is not assignable to type '(item: T, initial: boolean) => void'. Types of parameters 'item' and 'item' are incompatible. Type 'T' is not assignable to type 'PlanItem'.

ts/views/PlanItemScheduleView.ts(99,79): error TS2345: Argument of type 'this' is not assignable to parameter of type 'IControllerListener'. Type 'PlanItemScheduleView' is not assignable to type 'IControllerListener'. Types of property 'onAddedItem' are incompatible. Type '(item: T, initial: boolean) => void' is not assignable to type '(item: T, initial: boolean) => void'. Types of parameters 'item' and 'item' are incompatible. Type 'T' is not assignable to type 'PlanItem'.

Interfaces

namespace Planning {
    export interface IPlanItemScheduleView extends IView, IControllerListener<IPlanItem> {
        setTimespan(timespan: Timespan): void;
        getName(): string;
    }
}
namespace Planning {
    export interface IControllerListener<T> {
    /**
     * Notifies the listener that an item is added to the cache so it can add it to its view.
     * 
     * @template T
     * @param {T} item
     * @param {boolean} initial
     * 
     * @memberOf IControllerListener
     */
    onAddedItem<T>(item: T, initial: boolean): void;
    }
}

namespace Planning {
    export class PlanItemScheduleView<T extends PlanItem> implements IPlanItemScheduleView {

        public onAddedItem<T extends PlanItem>(item: T, initial: boolean): void {
            // implementation that needs properties on PlanItem
        }
    }
}

PlanItem is an abstract baseclass which is inherited by a few actual implementations. I have a few different kind of viwes that I construct like this:

  // Create the different views
  this._views = {
            personWeekView: new PlanItemScheduleView<Person>(this._options, this._logger, this),
            projectWeekView: new PlanItemScheduleView<Project>(this._options, this._logger, this),
            resourceWeekView: new PlanItemScheduleView<Resource>(this._options, this._logger, this),
        };

I thought I had this compiling before in an other version of tsc but I might be mistaken. How can I fix this?

1

1 Answers

2
votes

You do not need the generic parameter on onAddedItem, you can use the class parameter if you want onAddedItem to take the same argument type as the class. You could make IPlanItemScheduleView generic, so as to pass the PlanItemScheduleView type parameter down to IControllerListener

export interface IControllerListener<T> {
  onAddedItem(item: T, initial: boolean): void;
}
export interface IPlanItemScheduleView<T extends IPlanItem>  extends IControllerListener <T> {

}
export class PlanItemScheduleView<T extends PlanItem> implements IPlanItemScheduleView<T> {
  public onAddedItem(item: T, initial: boolean): void {
      // implementation that needs properties on PlanItem
  }
}

Note: edited to take into account feedback.