diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index e101a8c96a7..e00206baa00 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -424,6 +424,16 @@ interface LegacyOptions< // runtime compile only delimiters?: [string, string] + + /** + * #3468 + * + * type-only, used to assist Mixin's type inference, + * typescript will try to simplify the inferred `Mixin` type, + * with the `__differenciator`, typescript won't be able to combine different mixins, + * because the `__differenciator` will be different + */ + __differentiator?: keyof D | keyof C | keyof M } export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults' diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index 8dbf7ca29ff..ff04a0d6f3f 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -775,6 +775,41 @@ describe('extends with mixins', () => { expectError() // @ts-expect-error expectError() + + // #3468 + const CompWithD = defineComponent({ + data() { + return { foo: 1 } + } + }) + const CompWithC = defineComponent({ + computed: { + foo() { + return 1 + } + } + }) + const CompWithM = defineComponent({ methods: { foo() {} } }) + const CompEmpty = defineComponent({}) + + defineComponent({ + mixins: [CompWithD, CompEmpty], + mounted() { + expectType(this.foo) + } + }) + defineComponent({ + mixins: [CompWithC, CompEmpty], + mounted() { + expectType(this.foo) + } + }) + defineComponent({ + mixins: [CompWithM, CompEmpty], + mounted() { + expectType<() => void>(this.foo) + } + }) }) describe('compatibility w/ createApp', () => {