带有约束的打字稿泛型不能分配给泛型接口
Posted
技术标签:
【中文标题】带有约束的打字稿泛型不能分配给泛型接口【英文标题】:Typescript generic with constraint isn't assignable to generic interface 【发布时间】:2018-02-09 06:06:20 【问题描述】:我在 TypeScript 2.4.2 的泛型类中遇到错误,其约束与不太严格的接口不兼容。我收到以下错误:
ts/components/Schedule.ts(37,13): error TS2322: Type ' personWeekView: PlanItemScheduleView; projectWeekView:PlanItemScheduleView; r...' 不能分配给类型 'Map'。 属性“personWeekView”与索引签名不兼容。 类型“PlanItemScheduleView”不可分配给类型“IPlanItemScheduleView”。 属性“onAddedItem”的类型不兼容。 类型 '(item: T, initial: boolean) => void' 不可分配给类型 '(item: T, initial: boolean) => void'。 参数“item”和“item”的类型不兼容。 类型“T”不可分配给类型“PlanItem”。
ts/views/PlanItemScheduleView.ts(2,18):错误 TS2420:“PlanItemScheduleView”类错误地实现了“IPlanItemScheduleView”接口。 属性“onAddedItem”的类型不兼容。 类型 '(item: T, initial: boolean) => void' 不可分配给类型 '(item: T, initial: boolean) => void'。 参数“item”和“item”的类型不兼容。 类型“T”不可分配给类型“PlanItem”。
ts/views/PlanItemScheduleView.ts(99,79):错误 TS2345:“this”类型的参数不可分配给“IControllerListener”类型的参数。 类型“PlanItemScheduleView”不可分配给类型“IControllerListener”。 属性“onAddedItem”的类型不兼容。 类型 '(item: T, initial: boolean) => void' 不可分配给类型 '(item: T, initial: boolean) => 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
PlanItem 是一个抽象基类,由一些实际实现继承。我有几种不同的观点,我是这样构建的:
// 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),
;
我以为我之前在其他版本的 tsc 中进行过编译,但我可能弄错了。我该如何解决这个问题?
【问题讨论】:
【参考方案1】:onAddedItem
不需要泛型参数,如果您希望onAddedItem
采用与类相同的参数类型,则可以使用类参数。您可以将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
注意:已编辑以考虑反馈。
【讨论】:
这使得 onAddedItem 不太安全,因为根据您的建议,我可以为 onAddedItem 提供不同的派生类型,而不是将其缩小到仅在构造时提供的一种类型,这实际上是使用泛型的原因/模板类。 您的版本对类型的限制不超过传递给类的类型。您是说您希望 onAddedItem 接受从 PlanItem 派生的类型,但不接受 PlanItem 本身 是的,对于 personWeekView 实例,我只希望 Person 成为参数的类型,而不是任何其他派生的 PlanItem 类型。 我改了答案,现在onAddedItem
和类的参数类型一样,所以不能调用_views.personWeekView.onAddItem(new Project())
以上是关于带有约束的打字稿泛型不能分配给泛型接口的主要内容,如果未能解决你的问题,请参考以下文章