// Match event type name strings that are registered on GlobalEventHandlersEventMap... export type EventTypeRequiresDetail = T extends keyof GlobalEventHandlersEventMap ? // ...where the event detail is an object... GlobalEventHandlersEventMap[T] extends CustomEvent> ? // ...that is non-empty... GlobalEventHandlersEventMap[T] extends CustomEvent> ? never : // ...and has at least one non-optional property Partial extends GlobalEventHandlersEventMap[T]['detail'] ? never : T : never : never; // The inverse of the above (match any type that doesn't match EventTypeRequiresDetail) export type EventTypeDoesNotRequireDetail = T extends keyof GlobalEventHandlersEventMap ? GlobalEventHandlersEventMap[T] extends CustomEvent> ? GlobalEventHandlersEventMap[T] extends CustomEvent> ? T : Partial extends GlobalEventHandlersEventMap[T]['detail'] ? T : never : T : T; // `keyof EventTypesWithRequiredDetail` lists all registered event types that require detail export type EventTypesWithRequiredDetail = { [EventType in keyof GlobalEventHandlersEventMap as EventTypeRequiresDetail]: true; }; // `keyof EventTypesWithoutRequiredDetail` lists all registered event types that do NOT require detail export type EventTypesWithoutRequiredDetail = { [EventType in keyof GlobalEventHandlersEventMap as EventTypeDoesNotRequireDetail]: true; }; // Helper to make a specific property of an object non-optional type WithRequired = T & { [P in K]-?: T[P] }; // Given an event name string, get a valid type for the options to initialize the event that is more restrictive than // just CustomEventInit when appropriate (validate the type of the event detail, and require it to be provided if the // event requires it) export type ZincEventInit = T extends keyof GlobalEventHandlersEventMap ? GlobalEventHandlersEventMap[T] extends CustomEvent> ? GlobalEventHandlersEventMap[T] extends CustomEvent> ? CustomEventInit : Partial extends GlobalEventHandlersEventMap[T]['detail'] ? CustomEventInit : WithRequired, 'detail'> : CustomEventInit : CustomEventInit; // Given an event name string, get the type of the event export type GetCustomEventType = T extends keyof GlobalEventHandlersEventMap ? GlobalEventHandlersEventMap[T] extends CustomEvent ? GlobalEventHandlersEventMap[T] : CustomEvent : CustomEvent; // `keyof ValidEventTypeMap` is equivalent to `keyof GlobalEventHandlersEventMap` but gives a nicer error message export type ValidEventTypeMap = EventTypesWithRequiredDetail | EventTypesWithoutRequiredDetail; export function waitForEvent(el: HTMLElement, eventName: string) { return new Promise(resolve => { function done(event: Event) { if (event.target === el) { el.removeEventListener(eventName, done); resolve(); } } el.addEventListener(eventName, done); }); }