TypeScript允许对自定义事件进行类型化,以确保在处理其对象时的正确性,特别是在Web应用程序中或使用pub/sub模式时。对于事件类型化,通常使用带有参数化泛型类型的CustomEvent:
interface MyEventDetail { username: string; age: number; } const event = new CustomEvent<MyEventDetail>('user:create', { detail: { username: 'alice', age: 30 } }); document.addEventListener('user:create', (e: CustomEvent<MyEventDetail>) => { console.log(e.detail.username); });
关键细节:
CustomEvent<T>)在创建事件和处理它时一致。any或object。常常有人问:“如果事件是由第三方库创建的,能否在处理程序中直接将事件对象类型化为
CustomEvent<Type>?”
正确的回答是:只有在绝对确定该库通过带有泛型的CustomEvent生成事件的情况下,才可以。否则,类型化将是不正确的,可能会导致运行时错误。
示例:
document.addEventListener('some-event', (e: Event) => { // 错误:'e' 不一定是 CustomEvent const detail = (e as CustomEvent<{ id: number }>).detail; // 如果事件不是 CustomEvent,这将导致错误 });
故事
在项目中使用了pub/sub抽象,并通过简单的Event抛出事件,而不是使用CustomEvent。期望可以访问event.detail,但基本的Event没有这个字段,导致了沉默的undefined和难以捕捉的bug。
故事
团队的一部分通过any对自定义事件进行了类型化,以便"更快"地实现对不同场景的处理程序。结果,后来由于通过detail传递不同的数据结构而产生了错误,而TypeScript没有发出不一致的警告。
故事
在一个项目中,开始将事件类型化为CustomEvent<string>,同时通过detail传递复杂对象。错误地序列化了detail,导致在处理程序端需要额外执行JSON.parse并失去TypeScript内部的类型化。