Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types): support nuxt types for defineComponent #19789

Merged
merged 4 commits into from Mar 20, 2023

Conversation

rchl
Copy link

@rchl rchl commented Mar 18, 2023

πŸ”— Linked issue

❓ Type of change

  • πŸ“– Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

Support asyncData types in components exported using defineComponent function.

The existing code only handled Vue.extend which is no longer recommended in Vue 2.7 and also Volar defaults to defineComponent so the asyncData types didn't work properly in that case by default (unless manually wrapped with Vue.extend).

This adds new overloads for defineFunction that are slightly modified to support asyncData option, including inferring types both in the script tag and in the template. The original Vue 2.7 types have 5 overloads of defineComponent. I've added variants of first 3, skipping functional component cases. Since functional components don't have state, I think asyncData doesn't apply to those but maybe I'm wrong? Haven't investigated that.

Also added tests for both the definedComponent and Vue.extend cases.
This is equivalent to testing types within the "script" tag in the Vue SFC component. I haven't quite figured out how to test the "template" part but this is better than nothing.

To better visualize what modifications were done to the original overloads I've created this diff that shows a diff between the original and the "augmented with asyncData" types:

defineComponent Diff
--- /vue.d.ts	Sat Mar 18 13:20:40 2023
+++ /vue.d.ts	Sat Mar 18 13:23:59 2023
@@ -9,9 +9,10 @@
   Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
   Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
   Emits extends EmitsOptions = {},
-  EmitsNames extends string = string
+  EmitsNames extends string = string,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 >(
-  options: { functional?: never } & ComponentOptionsWithoutProps<
+  options: { functional?: never } & ComponentOptionsWithoutPropsAndAsyncData<
     {},
     RawBindings,
     D,
@@ -20,10 +21,19 @@
     Mixin,
     Extends,
     Emits,
-    EmitsNames
-  >
-): DefineComponent<{}, RawBindings, D, C, M, Mixin, Extends, Emits>
-
+    EmitsNames,
+    AsyncData
+  >
+): DefineComponent<
+  {},
+  RawBindings,
+  Merged<D, Awaited<ReturnType<AsyncData>>>,
+  C,
+  M,
+  Mixin,
+  Extends,
+  Emits
+>
 
 /**
  * overload 2: object format with array props declaration
@@ -41,9 +51,10 @@
   Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
   Emits extends EmitsOptions = {},
   EmitsNames extends string = string,
-  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
+  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 >(
-  options: { functional?: never } & ComponentOptionsWithArrayProps<
+  options: { functional?: never } & ComponentOptionsWithArrayPropsAndAsyncData<
     PropNames,
     RawBindings,
     D,
@@ -52,19 +63,20 @@
     Mixin,
     Extends,
     Emits,
-    EmitsNames
+    EmitsNames,
+    Readonly<{ [key in PropNames]?: any }>,
+    AsyncData
   >
 ): DefineComponent<
   Readonly<{ [key in PropNames]?: any }>,
   RawBindings,
-  D,
+  Merged<D, Awaited<ReturnType<AsyncData>>>,
   C,
   M,
   Mixin,
   Extends,
   Emits
 >
-
 
 /**
  * overload 3: object format with object props declaration
@@ -81,10 +93,11 @@
   Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
   Emits extends EmitsOptions = {},
   EmitsNames extends string = string,
-  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
+  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 >(
   options: HasDefined<Props> extends true
-    ? { functional?: never } & ComponentOptionsWithProps<
+    ? { functional?: never } & ComponentOptionsWithPropsAndAsyncData<
         PropsOptions,
         RawBindings,
         D,
@@ -94,9 +107,11 @@
         Extends,
         Emits,
         EmitsNames,
-        Props
+        Props,
+        ExtractDefaultPropTypes<PropsOptions>,
+        AsyncData
       >
-    : { functional?: never } & ComponentOptionsWithProps<
+    : { functional?: never } & ComponentOptionsWithPropsAndAsyncData<
         PropsOptions,
         RawBindings,
         D,
@@ -105,11 +120,22 @@
         Mixin,
         Extends,
         Emits,
-        EmitsNames
+        EmitsNames,
+        ExtractPropTypes<PropsOptions>,
+        AsyncData
       >
-): DefineComponent<PropsOptions, RawBindings, D, C, M, Mixin, Extends, Emits>
-
-export type ComponentOptionsWithProps<
+): DefineComponent<
+  PropsOptions,
+  RawBindings,
+  Merged<D, Awaited<ReturnType<AsyncData>>>,
+  C,
+  M,
+  Mixin,
+  Extends,
+  Emits
+>
+
+export type ComponentOptionsWithPropsAndAsyncData<
   PropsOptions = ComponentPropsOptions,
   RawBindings = Data,
   D = Data,
@@ -120,7 +146,8 @@
   Emits extends EmitsOptions = {},
   EmitsNames extends string = string,
   Props = ExtractPropTypes<PropsOptions>,
-  Defaults = ExtractDefaultPropTypes<PropsOptions>
+  Defaults = ExtractDefaultPropTypes<PropsOptions>,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 > = ComponentOptionsBase<
   Props,
   RawBindings,
@@ -133,12 +160,13 @@
   EmitsNames,
   Defaults
 > & {
-  props?: PropsOptions
+  props?: PropsOptions,
+  asyncData: AsyncData,
 } & ThisType<
     CreateComponentPublicInstance<
       Props,
       RawBindings,
-      D,
+      Merged<D, Awaited<ReturnType<AsyncData>>>,
       C,
       M,
       Mixin,
@@ -147,7 +175,7 @@
     >
   >
 
-export type ComponentOptionsWithArrayProps<
+export type ComponentOptionsWithArrayPropsAndAsyncData<
   PropNames extends string = string,
   RawBindings = Data,
   D = Data,
@@ -157,7 +185,8 @@
   Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
   Emits extends EmitsOptions = {},
   EmitsNames extends string = string,
-  Props = Readonly<{ [key in PropNames]?: any }>
+  Props = Readonly<{ [key in PropNames]?: any }>,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 > = ComponentOptionsBase<
   Props,
   RawBindings,
@@ -170,12 +199,13 @@
   EmitsNames,
   {}
 > & {
-  props?: PropNames[]
+  props?: PropNames[],
+  asyncData: AsyncData,
 } & ThisType<
     CreateComponentPublicInstance<
       Props,
       RawBindings,
-      D,
+      Merged<D, Awaited<ReturnType<AsyncData>>>,
       C,
       M,
       Mixin,
@@ -184,7 +214,7 @@
     >
   >
 
-export type ComponentOptionsWithoutProps<
+export type ComponentOptionsWithoutPropsAndAsyncData<
   Props = {},
   RawBindings = Data,
   D = Data,
@@ -193,7 +223,8 @@
   Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
   Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
   Emits extends EmitsOptions = {},
-  EmitsNames extends string = string
+  EmitsNames extends string = string,
+  AsyncData extends DefaultAsyncData = DefaultAsyncData,
 > = ComponentOptionsBase<
   Props,
   RawBindings,
@@ -206,12 +237,13 @@
   EmitsNames,
   {}
 > & {
-  props?: undefined
+  props?: undefined,
+  asyncData: AsyncData,
 } & ThisType<
     CreateComponentPublicInstance<
       Props,
       RawBindings,
-      D,
+      Merged<D, Awaited<ReturnType<AsyncData>>>,
       C,
       M,
       Mixin,

Oh, and I've also changed asyncData to not have Vue instance as this as that's not accurate. this is undefined in asyncData.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@codesandbox
Copy link

codesandbox bot commented Mar 18, 2023

CodeSandbox logoCodeSandbox logoΒ  Open in CodeSandbox Web Editor | VS Code | VS Code Insiders

@codecov-commenter
Copy link

codecov-commenter commented Mar 18, 2023

Codecov Report

Patch and project coverage have no change.

Comparison is base (4ce8b11) 65.96% compared to head (4ac1f5b) 65.96%.

Additional details and impacted files
@@           Coverage Diff           @@
##              2.x   #19789   +/-   ##
=======================================
  Coverage   65.96%   65.96%           
=======================================
  Files          93       93           
  Lines        4113     4113           
  Branches     1165     1165           
=======================================
  Hits         2713     2713           
  Misses       1133     1133           
  Partials      267      267           
Flag Coverage Ξ”
unittests 65.96% <ΓΈ> (ΓΈ)

Flags with carried forward coverage won't be shown. Click here to find out more.

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

β˜” View full report in Codecov by Sentry.
πŸ“’ Do you have feedback about the report comment? Let us know in this issue.

@danielroe danielroe added the 2.x label Mar 19, 2023
@danielroe danielroe changed the title fix(types): support inferring asyncData types with defineComponent feat(types): support nuxt types for defineComponent Mar 20, 2023
@danielroe danielroe merged commit 4b6a504 into nuxt:2.x Mar 20, 2023
13 checks passed
@rchl rchl deleted the fix/define-component-async-data branch March 20, 2023 22:00
@danielroe danielroe mentioned this pull request Jun 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants