improve types

This commit is contained in:
Rene Haas
2022-11-09 11:01:30 +01:00
parent 1c6b421062
commit 270b4453e6
8 changed files with 75 additions and 75 deletions
@@ -10,7 +10,7 @@ import {
AfterViewInit, AfterViewInit,
} from '@angular/core'; } from '@angular/core';
import { OverlayScrollbars } from 'overlayscrollbars'; import { OverlayScrollbars } from 'overlayscrollbars';
import type { PartialOptions, EventListeners, EventListenerMap } from 'overlayscrollbars'; import type { PartialOptions, EventListeners, EventListenerArgs } from 'overlayscrollbars';
import { OverlayScrollbarsDirective } from './overlayscrollbars.directive'; import { OverlayScrollbarsDirective } from './overlayscrollbars.directive';
const mergeEventListeners = (emits: EventListeners, events: EventListeners) => const mergeEventListeners = (emits: EventListeners, events: EventListeners) =>
@@ -43,13 +43,13 @@ export class OverlayScrollbarsComponent implements OnDestroy, AfterViewInit {
events?: EventListeners | false | null; events?: EventListeners | false | null;
@Output('osInitialized') @Output('osInitialized')
onInitialized = new EventEmitter<EventListenerMap['initialized']>(); onInitialized = new EventEmitter<EventListenerArgs['initialized']>();
@Output('osUpdated') @Output('osUpdated')
onUpdated = new EventEmitter<EventListenerMap['updated']>(); onUpdated = new EventEmitter<EventListenerArgs['updated']>();
@Output('osDestroyed') @Output('osDestroyed')
onDestroyed = new EventEmitter<EventListenerMap['destroyed']>(); onDestroyed = new EventEmitter<EventListenerArgs['destroyed']>();
@Output('osScroll') @Output('osScroll')
onScroll = new EventEmitter<EventListenerMap['scroll']>(); onScroll = new EventEmitter<EventListenerArgs['scroll']>();
@ViewChild('content') @ViewChild('content')
private contentRef?: ElementRef<HTMLDivElement>; private contentRef?: ElementRef<HTMLDivElement>;
@@ -7,7 +7,7 @@ import {
OverlayscrollbarsModule, OverlayscrollbarsModule,
} from '~/public-api'; } from '~/public-api';
import type { ComponentFixture } from '@angular/core/testing'; import type { ComponentFixture } from '@angular/core/testing';
import type { EventListenerMap } from 'overlayscrollbars'; import type { EventListenerArgs } from 'overlayscrollbars';
@Component({ @Component({
template: ` template: `
@@ -45,19 +45,19 @@ class Test {
@ViewChild('ref', { read: OverlayScrollbarsComponent }) @ViewChild('ref', { read: OverlayScrollbarsComponent })
ref?: OverlayScrollbarsComponent; ref?: OverlayScrollbarsComponent;
onInitialized(args: EventListenerMap['initialized']) { onInitialized(args: EventListenerArgs['initialized']) {
this.initialized?.(args); this.initialized?.(args);
} }
onUpdated(args: EventListenerMap['updated']) { onUpdated(args: EventListenerArgs['updated']) {
this.updated?.(args); this.updated?.(args);
} }
onDestroyed(args: EventListenerMap['destroyed']) { onDestroyed(args: EventListenerArgs['destroyed']) {
this.destroyed?.(args); this.destroyed?.(args);
} }
onScroll(args: EventListenerMap['scroll']) { onScroll(args: EventListenerArgs['scroll']) {
this.scroll?.(args); this.scroll?.(args);
} }
@@ -6,10 +6,10 @@ import type {
OverlayScrollbarsComponentRef, OverlayScrollbarsComponentRef,
} from './OverlayScrollbarsComponent.types'; } from './OverlayScrollbarsComponent.types';
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import type { EventListeners, EventListenerMap } from 'overlayscrollbars'; import type { EventListeners, EventListenerArgs } from 'overlayscrollbars';
type EmitEventsMap = { type EmitEventsMap = {
[N in keyof EventListenerMap]: `os${Capitalize<N>}`; [N in keyof EventListenerArgs]: `os${Capitalize<N>}`;
}; };
const emitEvents: EmitEventsMap = { const emitEvents: EmitEventsMap = {
@@ -27,10 +27,10 @@ const props = defineProps({
events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> }, events: { type: Object as PropType<OverlayScrollbarsComponentProps['events']> },
}); });
const emits = defineEmits<{ const emits = defineEmits<{
(name: 'osInitialized', ...args: EventListenerMap['initialized']): void; (name: 'osInitialized', ...args: EventListenerArgs['initialized']): void;
(name: 'osUpdated', ...args: EventListenerMap['updated']): void; (name: 'osUpdated', ...args: EventListenerArgs['updated']): void;
(name: 'osDestroyed', ...args: EventListenerMap['destroyed']): void; (name: 'osDestroyed', ...args: EventListenerArgs['destroyed']): void;
(name: 'osScroll', ...args: EventListenerMap['scroll']): void; (name: 'osScroll', ...args: EventListenerArgs['scroll']): void;
}>(); }>();
const elementRef = shallowRef<HTMLElement | null>(null); const elementRef = shallowRef<HTMLElement | null>(null);
@@ -72,7 +72,7 @@ watch(
).reduce<EventListeners>(<N extends keyof EventListeners>(obj: EventListeners, name: N) => { ).reduce<EventListeners>(<N extends keyof EventListeners>(obj: EventListeners, name: N) => {
const eventListener = currEvents[name]; const eventListener = currEvents[name];
obj[name] = [ obj[name] = [
(...args: EventListenerMap[N]) => (...args: EventListenerArgs[N]) =>
emits( emits(
emitEvents[name], emitEvents[name],
// @ts-ignore // @ts-ignore
@@ -32,7 +32,7 @@ import type { Options, PartialOptions } from '~/options';
import type { ScrollbarsHidingPluginInstance } from '~/plugins'; import type { ScrollbarsHidingPluginInstance } from '~/plugins';
import type { Initialization, PartialInitialization } from '~/initialization'; import type { Initialization, PartialInitialization } from '~/initialization';
type EnvironmentEventMap = { type EnvironmentEventArgs = {
z: []; z: [];
r: []; r: [];
}; };
@@ -88,8 +88,8 @@ export interface InternalEnvironment {
readonly _cssCustomProperties: boolean; readonly _cssCustomProperties: boolean;
readonly _staticDefaultInitialization: Initialization; readonly _staticDefaultInitialization: Initialization;
readonly _staticDefaultOptions: Options; readonly _staticDefaultOptions: Options;
_addZoomListener(listener: EventListener<EnvironmentEventMap, 'z'>): () => void; _addZoomListener(listener: EventListener<EnvironmentEventArgs, 'z'>): () => void;
_addResizeListener(listener: EventListener<EnvironmentEventMap, 'r'>): () => void; _addResizeListener(listener: EventListener<EnvironmentEventArgs, 'r'>): () => void;
_getDefaultInitialization(): Initialization; _getDefaultInitialization(): Initialization;
_setDefaultInitialization(newInitialization: PartialInitialization): Initialization; _setDefaultInitialization(newInitialization: PartialInitialization): Initialization;
_getDefaultOptions(): Options; _getDefaultOptions(): Options;
@@ -183,7 +183,7 @@ const createEnvironment = (): InternalEnvironment => {
const envDOM = createDOM(`<div class="${classNameEnvironment}"><div></div></div>`); const envDOM = createDOM(`<div class="${classNameEnvironment}"><div></div></div>`);
const envElm = envDOM[0] as HTMLElement; const envElm = envDOM[0] as HTMLElement;
const envChildElm = envElm.firstChild as HTMLElement; const envChildElm = envElm.firstChild as HTMLElement;
const [addEvent, , triggerEvent] = createEventListenerHub<EnvironmentEventMap>(); const [addEvent, , triggerEvent] = createEventListenerHub<EnvironmentEventArgs>();
const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache( const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache(
{ {
_initialValue: getNativeScrollbarSize(body, envElm, envChildElm), _initialValue: getNativeScrollbarSize(body, envElm, envChildElm),
@@ -40,7 +40,7 @@ export interface OnUpdatedEventListenerArgs {
/** /**
* A mapping between event names and their listener arguments. * A mapping between event names and their listener arguments.
*/ */
export type EventListenerMap = { export type EventListenerArgs = {
/** Triggered after all elements are initialized and appended. */ /** Triggered after all elements are initialized and appended. */
initialized: [instance: OverlayScrollbars]; initialized: [instance: OverlayScrollbars];
/** Triggered after an update. */ /** Triggered after an update. */
@@ -58,19 +58,19 @@ export type EventListenerMap = {
* [eventName: string]: EventListener | EventListener[] * [eventName: string]: EventListener | EventListener[]
* } * }
*/ */
export type EventListeners = GeneralEventListeners<EventListenerMap>; export type EventListeners = GeneralEventListeners<EventListenerArgs>;
/** An event listener. */ /** An event listener. */
export type EventListener<N extends keyof EventListenerMap> = GeneralEventListener< export type EventListener<N extends keyof EventListenerArgs> = GeneralEventListener<
EventListenerMap, EventListenerArgs,
N N
>; >;
/** A function which adds event listeners. */ /** A function which adds event listeners. */
export type AddEvent = GeneralAddEvent<EventListenerMap>; export type AddEvent = GeneralAddEvent<EventListenerArgs>;
/** A function which removes event listeners. */ /** A function which removes event listeners. */
export type RemoveEvent = GeneralRemoveEvent<EventListenerMap>; export type RemoveEvent = GeneralRemoveEvent<EventListenerArgs>;
/** A function which triggers event listeners. */ /** A function which triggers event listeners. */
export type TriggerEvent = GeneralTriggerEvent<EventListenerMap>; export type TriggerEvent = GeneralTriggerEvent<EventListenerArgs>;
+3 -3
View File
@@ -8,13 +8,13 @@ export type {
PartialOptions, PartialOptions,
ReadonlyOptions, ReadonlyOptions,
OverflowBehavior, OverflowBehavior,
ScrollbarsVisibilityBehavior as ScrollbarVisibilityBehavior, ScrollbarsVisibilityBehavior,
ScrollbarsAutoHideBehavior as ScrollbarAutoHideBehavior, ScrollbarsAutoHideBehavior,
} from '~/options'; } from '~/options';
export type { export type {
EventListenerMap,
EventListener, EventListener,
EventListeners, EventListeners,
EventListenerArgs,
OnUpdatedEventListenerArgs, OnUpdatedEventListenerArgs,
} from '~/eventListeners'; } from '~/eventListeners';
export type { export type {
@@ -20,7 +20,7 @@ import type { Options, PartialOptions, ReadonlyOptions } from '~/options';
import type { Plugin, OptionsValidationPluginInstance, PluginInstance } from '~/plugins'; import type { Plugin, OptionsValidationPluginInstance, PluginInstance } from '~/plugins';
import type { InitializationTarget } from '~/initialization'; import type { InitializationTarget } from '~/initialization';
import type { OverflowStyle } from '~/typings'; import type { OverflowStyle } from '~/typings';
import type { EventListenerMap, EventListener, EventListeners } from '~/eventListeners'; import type { EventListenerArgs, EventListener, EventListeners } from '~/eventListeners';
import type { import type {
ScrollbarsSetupElement, ScrollbarsSetupElement,
ScrollbarStructure, ScrollbarStructure,
@@ -184,27 +184,27 @@ export interface OverlayScrollbars {
* @param listener The listener which is invoked on that event. * @param listener The listener which is invoked on that event.
* @returns Returns a function which removes the added listeners. * @returns Returns a function which removes the added listeners.
*/ */
on<N extends keyof EventListenerMap>(name: N, listener: EventListener<N>): () => void; on<N extends keyof EventListenerArgs>(name: N, listener: EventListener<N>): () => void;
/** /**
* Adds multiple event listeners to the instance. * Adds multiple event listeners to the instance.
* @param name The name of the event. * @param name The name of the event.
* @param listener The listeners which are invoked on that event. * @param listener The listeners which are invoked on that event.
* @returns Returns a function which removes the added listeners. * @returns Returns a function which removes the added listeners.
*/ */
on<N extends keyof EventListenerMap>(name: N, listener: EventListener<N>[]): () => void; on<N extends keyof EventListenerArgs>(name: N, listener: EventListener<N>[]): () => void;
/** /**
* Removes an event listener from the instance. * Removes an event listener from the instance.
* @param name The name of the event. * @param name The name of the event.
* @param listener The listener which shall be removed. * @param listener The listener which shall be removed.
*/ */
off<N extends keyof EventListenerMap>(name: N, listener: EventListener<N>): void; off<N extends keyof EventListenerArgs>(name: N, listener: EventListener<N>): void;
/** /**
* Removes multiple event listeners from the instance. * Removes multiple event listeners from the instance.
* @param name The name of the event. * @param name The name of the event.
* @param listener The listeners which shall be removed. * @param listener The listeners which shall be removed.
*/ */
off<N extends keyof EventListenerMap>(name: N, listener: EventListener<N>[]): void; off<N extends keyof EventListenerArgs>(name: N, listener: EventListener<N>[]): void;
/** /**
* Updates the instance. * Updates the instance.
@@ -2,56 +2,56 @@ import { isArray, isBoolean, isFunction, isString } from '~/support/utils/types'
import { keys } from '~/support/utils/object'; import { keys } from '~/support/utils/object';
import { each, push, from, isEmptyArray, runEachAndClear } from '~/support/utils/array'; import { each, push, from, isEmptyArray, runEachAndClear } from '~/support/utils/array';
export type EventListener<EventMap extends Record<string, any[]>, N extends keyof EventMap> = ( export type EventListener<EventArgs extends Record<string, any[]>, N extends keyof EventArgs> = (
...args: EventMap[N] ...args: EventArgs[N]
) => void; ) => void;
export type EventListeners<EventMap extends Record<string, any[]>> = { export type EventListeners<EventArgs extends Record<string, any[]>> = {
[K in keyof EventMap]?: EventListener<EventMap, K> | EventListener<EventMap, K>[] | null; [K in keyof EventArgs]?: EventListener<EventArgs, K> | EventListener<EventArgs, K>[] | null;
}; };
export type RemoveEvent<EventMap extends Record<string, any[]>> = { export type RemoveEvent<EventArgs extends Record<string, any[]>> = {
<N extends keyof EventMap>(name?: N, listener?: EventListener<EventMap, N>): void; <N extends keyof EventArgs>(name?: N, listener?: EventListener<EventArgs, N>): void;
<N extends keyof EventMap>(name?: N, listener?: EventListener<EventMap, N>[]): void; <N extends keyof EventArgs>(name?: N, listener?: EventListener<EventArgs, N>[]): void;
<N extends keyof EventMap>( <N extends keyof EventArgs>(
name?: N, name?: N,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[] listener?: EventListener<EventArgs, N> | EventListener<EventArgs, N>[]
): void; ): void;
}; };
export type AddEvent<EventMap extends Record<string, any[]>> = { export type AddEvent<EventArgs extends Record<string, any[]>> = {
(eventListeners: EventListeners<EventMap>, pure?: boolean): () => void; (eventListeners: EventListeners<EventArgs>, pure?: boolean): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<EventMap, N>): () => void; <N extends keyof EventArgs>(name: N, listener: EventListener<EventArgs, N>): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<EventMap, N>[]): () => void; <N extends keyof EventArgs>(name: N, listener: EventListener<EventArgs, N>[]): () => void;
<N extends keyof EventMap>( <N extends keyof EventArgs>(
nameOrEventListeners: N | EventListeners<EventMap>, nameOrEventListeners: N | EventListeners<EventArgs>,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[] | boolean listener?: EventListener<EventArgs, N> | EventListener<EventArgs, N>[] | boolean
): () => void; ): () => void;
}; };
export type TriggerEvent<EventMap extends Record<string, any[]>> = { export type TriggerEvent<EventArgs extends Record<string, any[]>> = {
<N extends keyof EventMap>(name: N, args?: EventMap[N]): void; <N extends keyof EventArgs>(name: N, args?: EventArgs[N]): void;
}; };
export type EventListenerHub<EventMap extends Record<string, any[]>> = [ export type EventListenerHub<EventArgs extends Record<string, any[]>> = [
AddEvent<EventMap>, AddEvent<EventArgs>,
RemoveEvent<EventMap>, RemoveEvent<EventArgs>,
TriggerEvent<EventMap> TriggerEvent<EventArgs>
]; ];
const manageListener = <EventMap extends Record<string, any[]>, N extends keyof EventMap>( const manageListener = <EventArgs extends Record<string, any[]>, N extends keyof EventArgs>(
callback: (listener?: EventListener<EventMap, N>) => void, callback: (listener?: EventListener<EventArgs, N>) => void,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[] listener?: EventListener<EventArgs, N> | EventListener<EventArgs, N>[]
) => { ) => {
each(isArray(listener) ? listener : [listener], callback); each(isArray(listener) ? listener : [listener], callback);
}; };
export const createEventListenerHub = <EventMap extends Record<string, any[]>>( export const createEventListenerHub = <EventArgs extends Record<string, any[]>>(
initialEventListeners?: EventListeners<EventMap> initialEventListeners?: EventListeners<EventArgs>
): EventListenerHub<EventMap> => { ): EventListenerHub<EventArgs> => {
const events = new Map<keyof EventMap, Set<EventListener<EventMap, keyof EventMap>>>(); const events = new Map<keyof EventArgs, Set<EventListener<EventArgs, keyof EventArgs>>>();
const removeEvent: RemoveEvent<EventMap> = (name, listener) => { const removeEvent: RemoveEvent<EventArgs> = (name, listener) => {
if (name) { if (name) {
const eventSet = events.get(name); const eventSet = events.get(name);
manageListener((currListener) => { manageListener((currListener) => {
@@ -67,11 +67,11 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
} }
}; };
const addEvent: AddEvent<EventMap> = (( const addEvent: AddEvent<EventArgs> = ((
nameOrEventListeners: keyof EventMap | EventListeners<EventMap>, nameOrEventListeners: keyof EventArgs | EventListeners<EventArgs>,
listenerOrPure: listenerOrPure:
| EventListener<EventMap, keyof EventMap> | EventListener<EventArgs, keyof EventArgs>
| EventListener<EventMap, keyof EventMap>[] | EventListener<EventArgs, keyof EventArgs>[]
| boolean | boolean
) => { ) => {
if (isString(nameOrEventListeners)) { if (isString(nameOrEventListeners)) {
@@ -88,22 +88,22 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
removeEvent(); removeEvent();
} }
const eventListenerKeys = keys(nameOrEventListeners) as (keyof EventListeners<EventMap>)[]; const eventListenerKeys = keys(nameOrEventListeners) as (keyof EventListeners<EventArgs>)[];
const offFns: (() => void)[] = []; const offFns: (() => void)[] = [];
each(eventListenerKeys, (key) => { each(eventListenerKeys, (key) => {
const eventListener = (nameOrEventListeners as EventListeners<EventMap>)[key]; const eventListener = (nameOrEventListeners as EventListeners<EventArgs>)[key];
eventListener && push(offFns, addEvent(key, eventListener)); eventListener && push(offFns, addEvent(key, eventListener));
}); });
return runEachAndClear.bind(0, offFns); return runEachAndClear.bind(0, offFns);
}) as AddEvent<EventMap>; // sorry! }) as AddEvent<EventArgs>; // sorry!
const triggerEvent: TriggerEvent<EventMap> = (name, args) => { const triggerEvent: TriggerEvent<EventArgs> = (name, args) => {
const eventSet = events.get(name); const eventSet = events.get(name);
each(from(eventSet), (event) => { each(from(eventSet), (event) => {
if (args && !isEmptyArray(args)) { if (args && !isEmptyArray(args)) {
(event as (...eventArgs: EventMap[keyof EventMap]) => void).apply(0, args as any); (event as (...eventArgs: EventArgs[keyof EventArgs]) => void).apply(0, args as any);
} else { } else {
(event as () => void)(); (event as () => void)();
} }