Просмотр исходного кода

fix(compiler-sfc): raise specific warning for failed extends and allow ignoring extends

ref #8286
Evan You 2 лет назад
Родитель
Сommit
82350721a4

+ 29 - 0
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<Props>()
+      `)
+      ).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<Props>()
+      `))
+      ).not.toThrow(`@vue-ignore`)
+
+      expect(res.props).toStrictEqual({
+        foo: ['String']
+      })
+    })
   })
 })
 

+ 22 - 4
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
+        )
       }
     }
   }