Browse Source

feat(types): support mixins inference for new Vue() (#12737)

close #12730
gu 3 years ago
parent
commit
89a6b5e865
4 changed files with 166 additions and 34 deletions
  1. 24 9
      types/options.d.ts
  2. 38 1
      types/test/vue-test.ts
  3. 2 2
      types/v3-component-public-instance.d.ts
  4. 102 22
      types/vue.d.ts

+ 24 - 9
types/options.d.ts

@@ -3,6 +3,7 @@ import { VNode, VNodeData, VNodeDirective, NormalizedScopedSlot } from './vnode'
 import { SetupContext } from './v3-setup-context'
 import { DebuggerEvent } from './v3-generated'
 import { DefineComponent } from './v3-define-component'
+import { ComponentOptionsMixin } from './v3-component-options'
 
 type Constructor = {
   new (...args: any[]): any
@@ -93,7 +94,9 @@ export type ThisTypedComponentOptionsWithArrayProps<
   Methods,
   Computed,
   PropNames extends string,
-  SetupBindings
+  SetupBindings,
+  Mixin,
+  Extends
 > = object &
   ComponentOptions<
     V,
@@ -102,7 +105,9 @@ export type ThisTypedComponentOptionsWithArrayProps<
     Computed,
     PropNames[],
     Record<PropNames, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   > &
   ThisType<
     CombinedVueInstance<
@@ -111,7 +116,9 @@ export type ThisTypedComponentOptionsWithArrayProps<
       Methods,
       Computed,
       Readonly<Record<PropNames, any>>,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   >
 
@@ -124,7 +131,9 @@ export type ThisTypedComponentOptionsWithRecordProps<
   Methods,
   Computed,
   Props,
-  SetupBindings
+  SetupBindings,
+  Mixin,
+  Extends
 > = object &
   ComponentOptions<
     V,
@@ -133,7 +142,9 @@ export type ThisTypedComponentOptionsWithRecordProps<
     Computed,
     RecordPropsDefinition<Props>,
     Props,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   > &
   ThisType<
     CombinedVueInstance<
@@ -142,7 +153,9 @@ export type ThisTypedComponentOptionsWithRecordProps<
       Methods,
       Computed,
       Readonly<Props>,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   >
 
@@ -158,7 +171,9 @@ export interface ComponentOptions<
   Computed = DefaultComputed,
   PropsDef = PropsDefinition<DefaultProps>,
   Props = DefaultProps,
-  RawBindings = {}
+  RawBindings = {},
+  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+  Extends extends ComponentOptionsMixin = ComponentOptionsMixin
 > {
   data?: Data
   props?: PropsDef
@@ -217,12 +232,12 @@ export interface ComponentOptions<
   }
 
   parent?: Vue
-  mixins?: (ComponentOptions<Vue> | typeof Vue)[]
+  mixins?: (Mixin | ComponentOptions<Vue> | typeof Vue)[]
   name?: string
   // for SFC auto name inference w/ ts-loader check
   __name?: string
   // TODO: support properly inferred 'extends'
-  extends?: ComponentOptions<Vue> | typeof Vue
+  extends?: Extends | ComponentOptions<Vue> | typeof Vue
   delimiters?: [string, string]
   comments?: boolean
   inheritAttrs?: boolean

+ 38 - 1
types/test/vue-test.ts

@@ -1,4 +1,4 @@
-import Vue, { VNode } from '../index'
+import Vue, { VNode, defineComponent } from '../index'
 import { ComponentOptions } from '../options'
 
 class Test extends Vue {
@@ -246,3 +246,40 @@ const ComponentWithStyleInVNodeData = Vue.extend({
     ])
   }
 })
+
+// infer mixin type with new Vue() #12730
+new Vue({
+  mixins: [
+    defineComponent({
+      props: {
+        p1: String,
+        p2: {
+          type: Number,
+          default: 0
+        }
+      },
+      data() {
+        return {
+          foo: 123
+        }
+      },
+      computed: {
+        bar() {
+          return 123
+        }
+      }
+    }),
+    {
+      methods: {
+        hello(n: number) {}
+      }
+    }
+  ],
+  created() {
+    this.hello(this.foo)
+    this.hello(this.bar)
+    // @ts-expect-error
+    this.hello(this.p1)
+    this.hello(this.p2)
+  }
+})

+ 2 - 2
types/v3-component-public-instance.d.ts

@@ -79,11 +79,11 @@ type ExtractMixin<T> = {
   Mixin: MixinToOptionTypes<T>
 }[T extends ComponentOptionsMixin ? 'Mixin' : never]
 
-type IntersectionMixin<T> = IsDefaultMixinComponent<T> extends true
+export type IntersectionMixin<T> = IsDefaultMixinComponent<T> extends true
   ? OptionTypesType<{}, {}, {}, {}, {}, {}>
   : UnionToIntersection<ExtractMixin<T>>
 
-type UnwrapMixinsType<
+export type UnwrapMixinsType<
   T,
   Type extends OptionTypesKeys
 > = T extends OptionTypesType ? T[Type] : never

+ 102 - 22
types/vue.d.ts

@@ -13,7 +13,15 @@ import {
 import { VNode, VNodeData, VNodeChildren, NormalizedScopedSlot } from './vnode'
 import { PluginFunction, PluginObject } from './plugin'
 import { DefineComponent } from './v3-define-component'
-import { nextTick } from './v3-generated'
+import { nextTick, UnwrapNestedRefs, ShallowUnwrapRef } from './v3-generated'
+import {
+  UnwrapMixinsType,
+  IntersectionMixin
+} from './v3-component-public-instance'
+import {
+  ExtractComputedReturns,
+  ComponentOptionsMixin
+} from './v3-component-options'
 
 export interface CreateElement {
   (
@@ -100,12 +108,20 @@ export type CombinedVueInstance<
   Methods,
   Computed,
   Props,
-  SetupBindings = {}
-> = Data &
+  SetupBindings = {},
+  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
+  PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>
+> = UnwrapNestedRefs<UnwrapMixinsType<PublicMixin, 'D'>> &
+  Data &
+  UnwrapMixinsType<PublicMixin, 'M'> &
   Methods &
+  ExtractComputedReturns<UnwrapMixinsType<PublicMixin, 'C'>> &
   Computed &
+  UnwrapMixinsType<PublicMixin, 'P'> &
   Props &
   Instance &
+  ShallowUnwrapRef<UnwrapMixinsType<PublicMixin, 'B'>> &
   (SetupBindings extends void ? {} : SetupBindings)
 
 export type ExtendedVue<
@@ -114,9 +130,20 @@ export type ExtendedVue<
   Methods,
   Computed,
   Props,
-  SetupBindings = {}
+  SetupBindings = {},
+  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+  Extends extends ComponentOptionsMixin = ComponentOptionsMixin
 > = VueConstructor<
-  CombinedVueInstance<Instance, Data, Methods, Computed, Props, SetupBindings> &
+  CombinedVueInstance<
+    Instance,
+    Data,
+    Methods,
+    Computed,
+    Props,
+    SetupBindings,
+    Mixin,
+    Extends
+  > &
     Vue
 >
 
@@ -142,7 +169,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods = object,
     Computed = object,
     PropNames extends string = never,
-    SetupBindings = {}
+    SetupBindings = {},
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
   >(
     options?: ThisTypedComponentOptionsWithArrayProps<
       V,
@@ -150,7 +179,9 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): CombinedVueInstance<
     V,
@@ -158,7 +189,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     Record<PropNames, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
 
   /**
@@ -172,7 +205,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods = object,
     Computed = object,
     Props = object,
-    SetupBindings = {}
+    SetupBindings = {},
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
   >(
     options?: ThisTypedComponentOptionsWithRecordProps<
       V,
@@ -180,7 +215,9 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       Props,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): CombinedVueInstance<
     V,
@@ -188,7 +225,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     Record<keyof Props, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
 
   /**
@@ -211,7 +250,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     PropNames extends string = never,
-    SetupBindings = {}
+    SetupBindings = {},
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
   >(
     options?: ThisTypedComponentOptionsWithArrayProps<
       V,
@@ -219,7 +260,9 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<
     V,
@@ -227,22 +270,43 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     Record<PropNames, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
 
   /**
    * extend with object props
    */
-  extend<Data, Methods, Computed, Props, SetupBindings = {}>(
+  extend<
+    Data,
+    Methods,
+    Computed,
+    Props,
+    SetupBindings = {},
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
+  >(
     options?: ThisTypedComponentOptionsWithRecordProps<
       V,
       Data,
       Methods,
       Computed,
       Props,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
-  ): ExtendedVue<V, Data, Methods, Computed, Props, SetupBindings>
+  ): ExtendedVue<
+    V,
+    Data,
+    Methods,
+    Computed,
+    Props,
+    SetupBindings,
+    Mixin,
+    Extends
+  >
 
   /**
    * extend with functional + array props
@@ -287,7 +351,9 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     PropNames extends string = never,
-    SetupBindings = {}
+    SetupBindings = {},
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
   >(
     id: string,
     definition?: ThisTypedComponentOptionsWithArrayProps<
@@ -296,7 +362,9 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<
     V,
@@ -304,9 +372,19 @@ export interface VueConstructor<V extends Vue = Vue> {
     Methods,
     Computed,
     Record<PropNames, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
-  component<Data, Methods, Computed, Props, SetupBindings>(
+  component<
+    Data,
+    Methods,
+    Computed,
+    Props,
+    SetupBindings,
+    Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
+    Extends extends ComponentOptionsMixin = ComponentOptionsMixin
+  >(
     id: string,
     definition?: ThisTypedComponentOptionsWithRecordProps<
       V,
@@ -314,7 +392,9 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       Props,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<V, Data, Methods, Computed, Props, SetupBindings>
   component<PropNames extends string>(