]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types: enhance plugin type inference for better IDE support (#13063)
authorTycho <jh.leong@outlook.com>
Wed, 19 Mar 2025 03:44:32 +0000 (11:44 +0800)
committerGitHub <noreply@github.com>
Wed, 19 Mar 2025 03:44:32 +0000 (11:44 +0800)
* types: enhance plugin type inference for better JSDoc and IDE support

* test: clean up

* chore: tweaks

packages-private/dts-test/appUse.test-d.ts
packages/runtime-core/src/apiCreateApp.ts

index 065f695686560840d1b3e7c473625fe795ba6fd5..21d702c9c04a86a1f378f154df568d1bcbe1e8d6 100644 (file)
@@ -12,8 +12,11 @@ app.use(PluginWithoutType, 2)
 app.use(PluginWithoutType, { anything: 'goes' }, true)
 
 type PluginOptions = {
+  /** option1 */
   option1?: string
+  /** option2 */
   option2: number
+  /** option3 */
   option3: boolean
 }
 
@@ -25,6 +28,20 @@ const PluginWithObjectOptions = {
   },
 }
 
+const objectPluginOptional = {
+  install(app: App, options?: PluginOptions) {},
+}
+app.use(objectPluginOptional)
+app.use(
+  objectPluginOptional,
+  // Test JSDoc and `go to definition` for options
+  {
+    option1: 'foo',
+    option2: 1,
+    option3: true,
+  },
+)
+
 for (const Plugin of [
   PluginWithObjectOptions,
   PluginWithObjectOptions.install,
@@ -92,7 +109,27 @@ const PluginTyped: Plugin<PluginOptions> = (app, options) => {}
 
 // @ts-expect-error: needs options
 app.use(PluginTyped)
-app.use(PluginTyped, { option2: 2, option3: true })
+app.use(
+  PluginTyped,
+  // Test autocomplete for options
+  {
+    option1: '',
+    option2: 2,
+    option3: true,
+  },
+)
+
+const functionPluginOptional = (app: App, options?: PluginOptions) => {}
+app.use(functionPluginOptional)
+app.use(functionPluginOptional, { option2: 2, option3: true })
+
+// type optional params
+const functionPluginOptional2: Plugin<[options?: PluginOptions]> = (
+  app,
+  options,
+) => {}
+app.use(functionPluginOptional2)
+app.use(functionPluginOptional2, { option2: 2, option3: true })
 
 // vuetify usage
 const key: string = ''
index 3d53716de08660f135ddfb33355c6c61cefbb4b6..748de866f75ebfa50847da47af39cd15f07ada5c 100644 (file)
@@ -36,9 +36,9 @@ export interface App<HostElement = any> {
 
   use<Options extends unknown[]>(
     plugin: Plugin<Options>,
-    ...options: Options
+    ...options: NoInfer<Options>
   ): this
-  use<Options>(plugin: Plugin<Options>, options: Options): this
+  use<Options>(plugin: Plugin<Options>, options: NoInfer<Options>): this
 
   mixin(mixin: ComponentOptions): this
   component(name: string): Component | undefined
@@ -215,9 +215,11 @@ export type ObjectPlugin<Options = any[]> = {
 export type FunctionPlugin<Options = any[]> = PluginInstallFunction<Options> &
   Partial<ObjectPlugin<Options>>
 
-export type Plugin<Options = any[]> =
-  | FunctionPlugin<Options>
-  | ObjectPlugin<Options>
+export type Plugin<
+  Options = any[],
+  // TODO: in next major Options extends unknown[] and remove P
+  P extends unknown[] = Options extends unknown[] ? Options : [Options],
+> = FunctionPlugin<P> | ObjectPlugin<P>
 
 export function createAppContext(): AppContext {
   return {