From 74bf9a5c1bdf815906ee21659e2975c2bbad2786 Mon Sep 17 00:00:00 2001 From: nd0ut Date: Wed, 29 Nov 2023 17:30:31 +0800 Subject: [PATCH] fix(lr-upload-ctx-provider): import event types --- blocks/ShadowWrapper/ShadowWrapper.js | 16 +++----- blocks/UploadCtxProvider/UploadCtxProvider.js | 40 ++++++++++--------- types/events.d.ts | 17 +++++--- types/test/events.test-d.ts | 15 ------- types/test/global-events.test-d.ts | 10 +++++ types/test/lr-upload-ctx-provider.test-d.tsx | 21 ++++++++++ utils/mixinClass.js | 14 +++++++ 7 files changed, 83 insertions(+), 50 deletions(-) delete mode 100644 types/test/events.test-d.ts create mode 100644 types/test/global-events.test-d.ts create mode 100644 types/test/lr-upload-ctx-provider.test-d.tsx create mode 100644 utils/mixinClass.js diff --git a/blocks/ShadowWrapper/ShadowWrapper.js b/blocks/ShadowWrapper/ShadowWrapper.js index 5e78d2e57..eaef91370 100644 --- a/blocks/ShadowWrapper/ShadowWrapper.js +++ b/blocks/ShadowWrapper/ShadowWrapper.js @@ -5,18 +5,14 @@ import { waitForAttribute } from '../../utils/waitForAttribute.js'; const CSS_ATTRIBUTE = 'css-src'; /** - * @template T - * @typedef {new (...args: any[]) => T} GConstructor - */ - -/** - * @template {GConstructor} T + * @template {import('../../utils/mixinClass.js').GConstructor} T * @param {T} Base - * @returns {{ - * new (...args: ConstructorParameters): InstanceType & { + * @returns {import('../../utils/mixinClass.js').MixinClass< + * T, + * { * shadowReadyCallback(): void; - * }; - * } & Omit} + * } + * >} */ export function shadowed(Base) { // @ts-ignore diff --git a/blocks/UploadCtxProvider/UploadCtxProvider.js b/blocks/UploadCtxProvider/UploadCtxProvider.js index 050b4d7f3..4291d2636 100644 --- a/blocks/UploadCtxProvider/UploadCtxProvider.js +++ b/blocks/UploadCtxProvider/UploadCtxProvider.js @@ -1,7 +1,6 @@ // @ts-check import { UploaderBlock } from '../../abstract/UploaderBlock.js'; - class UploadCtxProviderClass extends UploaderBlock { requireCtxName = true; @@ -10,23 +9,26 @@ class UploadCtxProviderClass extends UploaderBlock { } } -export const UploadCtxProvider = UploadCtxProviderClass; - /** - * @typedef {typeof UploadCtxProviderClass & { - * addEventListener< - * T extends typeof import('./EventEmitter.js').EventType[keyof typeof import('./EventEmitter.js').EventType] - * >( - * type: T, - * listener: (e: CustomEvent) => void, - * options?: boolean | AddEventListenerOptions - * ): void; - * removeEventListener< - * T extends typeof import('./EventEmitter.js').EventType[keyof typeof import('./EventEmitter.js').EventType] - * >( - * type: T, - * listener: (e: CustomEvent) => void, - * options?: boolean | EventListenerOptions - * ): void; - * }} UploadCtxProvider + * @typedef {import('../../utils/mixinClass.js').MixinClass< + * typeof UploadCtxProviderClass, + * { + * addEventListener< + * T extends typeof import('./EventEmitter.js').EventType[keyof typeof import('./EventEmitter.js').EventType] + * >( + * type: T, + * listener: (e: CustomEvent) => void, + * options?: boolean | AddEventListenerOptions + * ): void; + * removeEventListener< + * T extends typeof import('./EventEmitter.js').EventType[keyof typeof import('./EventEmitter.js').EventType] + * >( + * type: T, + * listener: (e: CustomEvent) => void, + * options?: boolean | EventListenerOptions + * ): void; + * } + * >} UploadCtxProviderType */ + +export const UploadCtxProvider = /** @type {UploadCtxProviderType} */ (/** @type {unknown} */ (UploadCtxProviderClass)); diff --git a/types/events.d.ts b/types/events.d.ts index 265411844..c669ff7ce 100644 --- a/types/events.d.ts +++ b/types/events.d.ts @@ -1,18 +1,23 @@ -import type { GlobalEventPayload } from '../blocks/UploadCtxProvider/EventEmitter'; +import type { GlobalEventPayload, EventPayload } from '../blocks/UploadCtxProvider/EventEmitter'; -type CustomEventMap = { +export type GlobalEventMap = { [T in keyof GlobalEventPayload]: CustomEvent; }; + +export type EventMap = { + [T in keyof EventPayload]: CustomEvent; +}; + declare global { interface Window { - addEventListener( + addEventListener( type: T, - listener: (e: CustomEventMap[T]) => void, + listener: (e: GlobalEventMap[T]) => void, options?: boolean | AddEventListenerOptions ): void; - removeEventListener( + removeEventListener( type: T, - listener: (e: CustomEventMap[T]) => void, + listener: (e: GlobalEventMap[T]) => void, options?: boolean | EventListenerOptions ): void; } diff --git a/types/test/events.test-d.ts b/types/test/events.test-d.ts deleted file mode 100644 index 5b269b9c1..000000000 --- a/types/test/events.test-d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { expectType } from 'tsd'; -import { GlobalEventPayload } from '..'; -import type { EventPayload, UploadCtxProvider } from '../..'; - -window.addEventListener('LR_DATA_OUTPUT', (e) => { - expectType>(e); -}, { once: true }); - -const ctx: UploadCtxProvider = null as unknown as UploadCtxProvider; -ctx.addEventListener( - 'data-output', - (e) => { - expectType>(e); - } -); diff --git a/types/test/global-events.test-d.ts b/types/test/global-events.test-d.ts new file mode 100644 index 000000000..c4d549058 --- /dev/null +++ b/types/test/global-events.test-d.ts @@ -0,0 +1,10 @@ +import { expectType } from 'tsd'; +import { GlobalEventPayload } from '..'; + +window.addEventListener( + 'LR_DATA_OUTPUT', + (e) => { + expectType>(e); + }, + { once: true } +); diff --git a/types/test/lr-upload-ctx-provider.test-d.tsx b/types/test/lr-upload-ctx-provider.test-d.tsx new file mode 100644 index 000000000..e706bf332 --- /dev/null +++ b/types/test/lr-upload-ctx-provider.test-d.tsx @@ -0,0 +1,21 @@ +import { expectType } from 'tsd'; +import { EventMap, UploadCtxProvider } from '../..'; + +const instance = new UploadCtxProvider(); + +instance.addFileFromUrl('https://example.com/image.png'); +instance.uploadCollection.size; +instance.setOrAddState('fileId', 'uploading'); + +instance.addEventListener('data-output', (e) => { + expectType(e); + + // @ts-expect-error - wrong event type + expectType(e); +}); + +const onDataOutput = (e: EventMap['data-output']) => { + // noop +} + +instance.addEventListener('data-output', onDataOutput); diff --git a/utils/mixinClass.js b/utils/mixinClass.js new file mode 100644 index 000000000..356903504 --- /dev/null +++ b/utils/mixinClass.js @@ -0,0 +1,14 @@ +/** + * @template T + * @typedef {new (...args: any[]) => T} GConstructor + */ + +/** + * @template {GConstructor} Base + * @template {Record} [InstanceProperties={}] Default is `{}` + * @typedef {{ + * new (...args: ConstructorParameters): InstanceProperties & InstanceType; + * } & Omit} MixinClass + */ + +export {};