Repository: vuejs/vue
Pull request: feat(types): new Vue() improvements (#12730)

<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->

<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->

**What kind of change does this PR introduce?** (check at least one)

- [ ] Bugfix
- [x] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Build-related changes
- [ ] Other, please describe:

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [ ] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [x] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

**Other information:**

Type inference improvements, close #12730 

Changed files:
filename: types/options.d.ts
patch: @@ -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

filename: types/test/vue-test.ts
patch: @@ -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)
+  }
+})

filename: types/v3-component-public-instance.d.ts
patch: @@ -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

filename: types/vue.d.ts
patch: @@ -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,23 +169,29 @@ 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,
       Data,
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): CombinedVueInstance<
     V,
     Data,
     Methods,
     Computed,
     Record<PropNames, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
 
   /**
@@ -172,23 +205,29 @@ 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,
       Data,
       Methods,
       Computed,
       Props,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): CombinedVueInstance<
     V,
     Data,
     Methods,
     Computed,
     Record<keyof Props, any>,
-    SetupBindings
+    SetupBindings,
+    Mixin,
+    Extends
   >
 
   /**
@@ -211,38 +250,63 @@ 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,
       Data,
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<
     V,
     Data,
     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,25 +362,39 @@ export interface VueConstructor<V extends Vue = Vue> {
       Methods,
       Computed,
       PropNames,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<
     V,
     Data,
     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,
       Data,
       Methods,
       Computed,
       Props,
-      SetupBindings
+      SetupBindings,
+      Mixin,
+      Extends
     >
   ): ExtendedVue<V, Data, Methods, Computed, Props, SetupBindings>
   component<PropNames extends string>(