gpt4 book ai didi

javascript - 类型中缺少属性,但类型中需要属性

转载 作者:行者123 更新时间:2023-12-04 09:32:34 26 4
gpt4 key购买 nike

我正在尝试在 TypeScript 上实现简单的事件调度程序。
我的自定义类型声明如下:events.d.ts :

type AppEvent = { [key: string]: any }

type AppEventListener<T> = <T extends AppEvent>(event: T) => void;
当我在这个函数中传递任何对象时
   public addListener<T extends AppEvent>(event: T, listener: AppEventListener<T>)
我收到以下错误:
Argument of type '(event: TestEvent) => void' is not assignable to parameter of type 'AppEventListener<typeof TestEvent>'.
Types of parameters 'event' and 'event' are incompatible.
Type 'T' is not assignable to type 'TestEvent'.
Property 'name' is missing in type 'AppEvent' but required in type 'TestEvent'.
所以,这个类型 AppEvent不能有任何附加属性。如何让它发挥作用?任何帮助表示赞赏。
完整代码示例:
class EventDispatcher {
private listeners: Map<AppEvent, Array<AppEventListener<AppEvent>>>

constructor() {
this.listeners = new Map();
}

public dispatch<T extends AppEvent>(event: T): void {
const listeners = this.listeners.get(event.constructor);
if (listeners) {
listeners.forEach((callback) => {
callback(event);
});
}
}

public addListener<T extends AppEvent>(event: T, listener: AppEventListener<T>): void {
let listeners = this.listeners.get(event);
if (!listeners) {
listeners = [listener];
this.listeners.set(event, listeners);
} else {
listeners.push(listener);
}
}
}

class TestEvent {
public name: string = ''
}

const dispatcher = new EventDispatcher();
const listener = (event: TestEvent) => {
console.dir(event);
};
dispatcher.addListener(TestEvent, listener);

const event = new TestEvent('name');
dispatcher.dispatch(event);

最佳答案

看起来你应该制作 AppEventLister引用非泛型函数的泛型类型,如下所示:

type AppEventListener<T> = (event: T) => void;
您说的是“ AppEventListener<T> 将发生 T 类型的事件”。这就是你想要的,对吧?

您的原始定义是泛型类型,指的是泛型函数,具有两个同名的不同泛型参数,相当于
type AppEventListenerBad<T> = <U>(event: U) => void;
(重命名不会改变类型;它只是让类型参数名称阴影发生了什么更清楚)意思是“ AppEventListener<T> 将完全忽略 T 并接受调用者的任何类型的事件 U想要指定”,这不太可能是您的意思。这就是你的错误来自: (event: TestEvent) => void不能分配给 <U>(event: U) => void .

一旦你这样做了,很多其他的问题就解决了,但它们可能会带来其他的问题。一个主要的原因是 standard library typings for Map 表示来自 K 类型键的非常基本的映射到 V 类型的值.它没有办法说 K 的某些子类型的键映射到 V 的程序确定子类型的值.在您的情况下,您可以为您使用 Map 的方式创建一个新界面:
interface AppEventListenerMap {
get<T>(x: T): Array<AppEventListener<T>> | undefined;
set<T>(x: T, val: Array<AppEventListener<T>>): void;
}
然后在 EventDispatcher你做 listeners属性 AppEventListenerMap 类型的值:
class EventDispatcher {
private listeners: AppEventListenerMap;

constructor() {
this.listeners = new Map();
}
这将主要使您的代码示例工作,除了您似乎正在使用 event 的事实。有时作为键,并使用 event.constructor作为其他时间的关键。这种不一致似乎是错误的,您可能需要准确确定类型关系才能使其正常工作。
无论如何,希望这会有所帮助;祝你好运!
Playground link to code

关于javascript - 类型中缺少属性,但类型中需要属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62766007/

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