diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index 240497310ee..dd47ae269c6 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -755,6 +755,35 @@ describe('resolveType', () => { `) ).not.toThrow() }) + + test('error against failed extends', () => { + expect(() => + resolve(` + import type Base from 'unknown' + interface Props extends Base {} + defineProps() + `) + ).toThrow(`@vue-ignore`) + }) + + test('allow ignoring failed extends', () => { + let res: any + + expect( + () => + (res = resolve(` + import type Base from 'unknown' + interface Props extends /*@vue-ignore*/ Base { + foo: string + } + defineProps() + `)) + ).not.toThrow(`@vue-ignore`) + + expect(res.props).toStrictEqual({ + foo: ['String'] + }) + }) }) }) diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 6b43be582d5..e79d21f8419 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -322,11 +322,29 @@ function resolveInterfaceMembers( const base = typeElementsToMap(ctx, node.body.body, node._ownerScope) if (node.extends) { for (const ext of node.extends) { - const { props } = resolveTypeElements(ctx, ext, scope) - for (const key in props) { - if (!hasOwn(base.props, key)) { - base.props[key] = props[key] + if ( + ext.leadingComments && + ext.leadingComments.some(c => c.value.includes('@vue-ignore')) + ) { + continue + } + try { + const { props } = resolveTypeElements(ctx, ext, scope) + for (const key in props) { + if (!hasOwn(base.props, key)) { + base.props[key] = props[key] + } } + } catch (e) { + ctx.error( + `Failed to resolve extends base type.\nIf this previously worked in 3.2, ` + + `you can instruct the compiler to ignore this extend by adding ` + + `/* @vue-ignore */ before it, for example:\n\n` + + `interface Props extends /* @vue-ignore */ Base {}\n\n` + + `Note: both in 3.2 or with the ignore, the properties in the base ` + + `type are treated as fallthrough attrs at runtime.`, + ext + ) } } }