gpt4 book ai didi

node.js - 扩展事件定义 - 接口(interface)错误地实现了接口(interface)

转载 作者:行者123 更新时间:2023-12-01 09:40:59 26 4
gpt4 key购买 nike

我正在尝试使用与以下示例中同名的接口(interface)和类在我的代码中强制执行事件定义:

export declare interface ClientEvents {
on(event: "event_name", data: (data: string) => void) : this;
emit(event: "event_name", data: string) : boolean;
}

export class ClientEvents extends EventEmitter {}

这对于 IDE 完成本身很有效,并确保只有这些事件由事件对象广播。

当我尝试扩展这个接口(interface)时,问题就来了,如下:

export declare interface SpecificClientEvents extends ClientEvents {
on(event: "child_event_name", data: (data: string) => void) : this;
emit(event: "child_event_name", data: string) : boolean;
}

export class SpecificClientEvents extends ClientEvents {}

我收到以下错误:

TS2430:接口(interface)“SpecificClientEvents”错误地扩展了接口(interface)“ClientEvents”。 用于接口(interface)

TS2415:类 'SpecificClientEvents' 错误地扩展了基类 'ClientEvents'。 用于类

我还尝试按照以下示例将类和接口(interface)分成单独的定义:

export interface ClientEventDefinitions {
on(event: "event_name", data: (data: string) => void) : this;
emit(event: "event_name", data: string) : boolean;
}

export class ClientEvents extends EventEmitter implements ClientEventDefinitions {}

export interface SpecificClientEventDefinitions {
on(event: "child_event_name", data: (data: string) => void) : this;
emit(event: "child_event_name", data: string) : boolean;
}

export class SpecificClientEvents extends ClientEvents implements SpecificClientEventDefinitions {}

这编译正常,但我的 IDE 没有像类和接口(interface)具有相同名称时那样检测事件名称。这可能是IDE的问题吗?这不适用于父类和子类。

我还能够使用第二个示例执行 new SpecificClientEvents().emit("an event that is not defined"); 而不会出现任何错误。

编辑:

如果我手动将父接口(interface)中的方法添加到子接口(interface),这绝对可以正常工作。但是,如果我需要手动添加方法,那么首先扩展父级有什么意义呢?

编辑 2:

我选择使用 strict event emitter package用下面的代码来满足我的需求

export type ClientEventEmitter = StrictEventEmitter<EventEmitter, ClientEvents>;

export interface ClientEvents {
event_name: (data: string) => void;
}

export type SpecificClientEventsEmitter = StrictEventEmitter<EventEmitter, SpecificClientEvents>;

export interface SpecificClientEvents extends ClientEvents {
child_event_name: (data: string) => void;
}

最佳答案

我想您可能没有意识到您正在使用一个名为 string literal types 的功能,这意味着您的两个接口(interface)具有不兼容的类型,并且您的第一个示例具有预期的行为。

为清楚起见,这里有一个简化版本:

interface A {
prop: 'String literal type';
}

interface B extends A {
prop: 'Another string literal type';
}

这会给您一条错误消息:Type '"Another string literal type"' is not assignable to type '"String literal type"'

I'm also able to execute new SpecificClientEvents().emit("an event that isn't defined"); without any errors using the 2nd example.

这似乎是因为 implements不强制使用 SpecificClientEventDefinitions 中的字符串文字类型和 SpecificClientEvents类改为使用 EventEmitter 中的类型(string | symbol)。

这是一种使用泛型类的替代方法,我认为它可以解决您的问题:

export class ClientEvents<T extends string> extends EventEmitter {
on(event: T, data: (data: string) => void): this {
return super.on(event, data);
}
emit(event: T, data: string): boolean {
return super.emit(event, data);
}
}

当您使用 new ClientEvents<'special_event_name'>() 创建新发射器时使用此代码, onemit函数将需要带有 'special_event_name' 的事件类型。

关于node.js - 扩展事件定义 - 接口(interface)错误地实现了接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60300587/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com