带有约束的Typescript泛型为';t可分配给通用接口

带有约束的Typescript泛型为';t可分配给通用接口,typescript,generics,Typescript,Generics,在TypeScript 2.4.2中,我在一个泛型类上遇到一个错误,该泛型类的约束与不太严格的接口不兼容。我得到以下错误: ts/components/Schedule.ts(37,13):错误TS2322:类型“{personWeekView:PlanItemScheduleView;projectWeekView:PlanItemScheduleView;r..”不可分配给类型“Map”。 属性“personWeekView”与索引签名不兼容。 类型“PlanItemScheduleView

在TypeScript 2.4.2中,我在一个泛型类上遇到一个错误,该泛型类的约束与不太严格的接口不兼容。我得到以下错误:

ts/components/Schedule.ts(37,13):错误TS2322:类型“{personWeekView:PlanItemScheduleView;projectWeekView:PlanItemScheduleView;r..”不可分配给类型“Map”。 属性“personWeekView”与索引签名不兼容。 类型“PlanItemScheduleView”不可分配给类型“IPlanItemScheduleView”。 属性“onAddedItem”的类型不兼容。 类型'(项目:T,初始值:布尔)=>void'不可分配给类型'(项目:T,初始值:布尔)=>void'。 参数“item”和“item”的类型不兼容。 类型“T”不可分配给类型“PlanItem”

ts/views/PlanItemScheduleView.ts(2,18):错误TS2420:类“PlanItemScheduleView”未正确实现接口“IPlanItemScheduleView”。 属性“onAddedItem”的类型不兼容。 类型'(项目:T,初始值:布尔)=>void'不可分配给类型'(项目:T,初始值:布尔)=>void'。 参数“item”和“item”的类型不兼容。 类型“T”不可分配给类型“PlanItem”

ts/views/PlanItemScheduleView.ts(99,79):错误TS2345:类型为“this”的参数不能分配给类型为“IControllerListener”的参数。 类型“PlanItemScheduleView”不可分配给类型“IControllerListener”。 属性“onAddedItem”的类型不兼容。 类型'(项目:T,初始值:布尔)=>void'不可分配给类型'(项目:T,初始值:布尔)=>void'。 参数“item”和“item”的类型不兼容。 类型“T”不可分配给类型“PlanItem”

接口

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
        }
    }
}
命名空间规划{
导出接口IPlanItemScheduleView扩展了IView、IControllerListener{
setTimespan(timespan:timespan):无效;
getName():字符串;
}
}
名称空间规划{
导出接口IControllerListener{
/**
*通知侦听器某个项已添加到缓存中,以便可以将其添加到其视图中。
* 
*@T模板
*@param{T}项
*@param{boolean}初始值
* 
*@memberOf-IControllerListener
*/
onAddedItem(项:T,首字母:boolean):void;
}
}
名称空间规划{
导出类PlanItemScheduleView实现IPlanItemScheduleView{
公共onAddedItem(项:T,首字母:布尔):void{
//在PlanItem上需要属性的实现
}
}
}
PlanItem是一个抽象基类,由一些实际实现继承。我有一些不同类型的Viwe,我是这样构造的:

  // 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),
        };
//创建不同的视图
这是您的看法{
personWeekView:new PlanItemScheduleView(此._选项,此._记录器,此),
projectWeekView:new PlanItemScheduleView(此._选项,此._记录器,此),
resourceWeekView:new PlanItemScheduleView(此._选项,此._记录器,此),
};

我以为我以前在其他版本的tsc中有过这种编译,但我可能弄错了。我如何解决这个问题呢?

您不需要
onAddedItem
上的泛型参数,如果希望
onAddedItem
采用与类相同的参数类型,可以使用class参数。您可以使用
IPlanItemScheduleView
泛型,以便将
PlanItemScheduleView
type参数向下传递到
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
  }
}
导出接口IControllerListener{
onAddedItem(项:T,首字母:boolean):void;
}
导出接口IPlanItemScheduleView扩展了IControllerListener{
}
导出类PlanItemScheduleView实现IPlanItemScheduleView{
公共onAddedItem(项:T,首字母:布尔):void{
//在PlanItem上需要属性的实现
}
}

注意:编辑以考虑反馈。

您不需要
onAddedItem
上的泛型参数,如果希望
onAddedItem
采用与类相同的参数类型,可以使用class参数。您可以将
IPlanItemScheduleView
设置为泛型,以便传递
PlanItemScheduleView
类型参数下至
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
  }
}
导出接口IControllerListener{
onAddedItem(项:T,首字母:boolean):void;
}
导出接口IPlanItemScheduleView扩展了IControllerListener{
}
导出类PlanItemScheduleView实现IPlanItemScheduleView{
公共onAddedItem(项:T,首字母:布尔):void{
//在PlanItem上需要属性的实现
}
}

注意:编辑以考虑反馈。

这会降低onAddedItem的安全性,因为根据您的建议,我可以为onAddedItem提供不同的派生类型,而不是将其缩小为构造时提供的一种类型,这实际上是使用泛型/模板类的原因。您的版本不限制类型多于传递给类的类型。您是说希望onAddedItem接受从PlanItem派生的类型,而不是PlanItem本身是的,在personWeekView实例中,我只希望Person是参数的类型,而不是任何其他派生的PlanItem类型。我更改了答案,现在
onAddedItem
tak与类的参数类型相同,因此不能调用
\u views.personWeekView.onAddItem(new Project())
这会降低onAddedItem的安全性,因为根据您的建议,我可以为onAddedItem提供不同的派生类型,而不是将其缩小为构造时提供的一种类型,这实际上是使用泛型/模板类的原因。您的版本对类型的限制不会超过传递给c的类型姑娘,你是说你想要奥纳德