فهرست منبع

@uppy/core: add utility type to help define plugin option types (#4885)

Antoine du Hamel 1 سال پیش
والد
کامیت
b7e8a08e75

+ 7 - 2
packages/@uppy/core/src/BasePlugin.ts

@@ -21,6 +21,11 @@ export type PluginOpts = {
   [key: string]: unknown
 }
 
+export type DefinePluginOpts<
+  Opts extends PluginOpts,
+  AlwaysDefinedKeys extends string,
+> = Opts & Required<Pick<Opts, AlwaysDefinedKeys>>
+
 export default class BasePlugin<
   Opts extends PluginOpts,
   M extends Meta,
@@ -43,9 +48,9 @@ export default class BasePlugin<
 
   VERSION: string
 
-  constructor(uppy: Uppy<M, B>, opts?: Partial<Opts>) {
+  constructor(uppy: Uppy<M, B>, opts?: Opts) {
     this.uppy = uppy
-    this.opts = (opts ?? {}) as Opts
+    this.opts = opts ?? ({} as Opts)
   }
 
   getPluginState(): PluginState {

+ 58 - 22
packages/@uppy/core/src/Uppy.test.ts

@@ -10,7 +10,10 @@ import prettierBytes from '@transloadit/prettier-bytes'
 import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
 import Core from './index.ts'
 import UIPlugin from './UIPlugin.ts'
-import BasePlugin, { type PluginOpts } from './BasePlugin.ts'
+import BasePlugin, {
+  type DefinePluginOpts,
+  type PluginOpts,
+} from './BasePlugin.ts'
 import { debugLogger } from './loggers.ts'
 import AcquirerPlugin1 from './mocks/acquirerPlugin1.ts'
 import AcquirerPlugin2 from './mocks/acquirerPlugin2.ts'
@@ -64,30 +67,63 @@ describe('src/Core', () => {
     })
 
     it('should be able to .use() without passing generics again', () => {
-      interface TestOpts extends PluginOpts {
-        foo?: string
-        bar: string
+      {
+        interface TestOpts extends PluginOpts {
+          foo?: string
+          bar: string
+        }
+        class TestPlugin<M extends Meta, B extends Body> extends BasePlugin<
+          TestOpts,
+          M,
+          B
+        > {
+          foo: string
+
+          bar: string
+
+          constructor(uppy: Core<M, B>, opts: TestOpts) {
+            super(uppy, opts)
+            this.id = 'Test'
+            this.type = 'acquirer'
+            this.foo = this.opts.foo ?? 'defaultFoo'
+            this.bar = this.opts.bar
+          }
+        }
+        new Core().use(TestPlugin)
+        new Core().use(TestPlugin, { foo: '', bar: '' })
+        // @ts-expect-error boolean not allowed
+        new Core().use(TestPlugin, { bar: false })
+        // @ts-expect-error missing option
+        new Core().use(TestPlugin, { foo: '' })
       }
-      class TestPlugin<M extends Meta, B extends Body> extends BasePlugin<
-        TestOpts,
-        M,
-        B
-      > {
-        foo: string
-
-        constructor(uppy: Core<M, B>, opts: TestOpts) {
-          super(uppy, opts)
-          this.id = 'Test'
-          this.type = 'acquirer'
-          this.foo = opts?.foo ?? 'bar'
+
+      {
+        interface TestOpts extends PluginOpts {
+          foo?: string
+          bar?: string
+        }
+        const defaultOptions = {
+          foo: 'defaultFoo',
         }
+        class TestPlugin<M extends Meta, B extends Body> extends BasePlugin<
+          DefinePluginOpts<TestOpts, keyof typeof defaultOptions>,
+          M,
+          B
+        > {
+          constructor(uppy: Core<M, B>, opts?: TestOpts) {
+            super(uppy, { ...defaultOptions, ...opts })
+            this.id = this.opts.id ?? 'Test'
+            this.type = 'acquirer'
+          }
+        }
+
+        new Core().use(TestPlugin)
+        new Core().use(TestPlugin, { foo: '', bar: '' })
+        new Core().use(TestPlugin, { foo: '' })
+        new Core().use(TestPlugin, { bar: '' })
+        // @ts-expect-error boolean not allowed
+        new Core().use(TestPlugin, { foo: false })
       }
-      new Core().use(TestPlugin)
-      new Core().use(TestPlugin, { foo: '', bar: '' })
-      // @ts-expect-error boolean not allowed
-      new Core().use(TestPlugin, { foo: false })
-      // @ts-expect-error missing option
-      new Core().use(TestPlugin, { foo: '' })
     })
 
     it('should prevent the same plugin from being added more than once', () => {

+ 1 - 1
packages/@uppy/core/src/Uppy.ts

@@ -1662,7 +1662,7 @@ export class Uppy<M extends Meta, B extends Body> {
   /**
    * Registers a plugin with Core.
    */
-  use<T extends typeof BasePlugin<any, M, B> | typeof UIPlugin<any, M, B>>(
+  use<T extends typeof BasePlugin<any, M, B>>(
     Plugin: T,
     opts?: ConstructorParameters<T>[1],
   ): this {

+ 2 - 2
packages/@uppy/status-bar/src/StatusBar.tsx

@@ -1,5 +1,6 @@
 import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
 import type { Uppy, State } from '@uppy/core/src/Uppy.ts'
+import type { DefinePluginOpts } from '@uppy/core/lib/BasePlugin.ts'
 import { UIPlugin } from '@uppy/core'
 import emaFilter from '@uppy/utils/lib/emaFilter'
 import getTextDirection from '@uppy/utils/lib/getTextDirection'
@@ -72,8 +73,7 @@ const defaultOptions = {
  * progress percentage and time remaining.
  */
 export default class StatusBar<M extends Meta, B extends Body> extends UIPlugin<
-  StatusBarOptions &
-    Required<Pick<StatusBarOptions, keyof typeof defaultOptions>>,
+  DefinePluginOpts<StatusBarOptions, keyof typeof defaultOptions>,
   M,
   B
 > {