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

fix(compiler-sfc): handle vue-ignore on leading intersection/union type (#14950)

close #12254
ifer47 6 дней назад
Родитель
Сommit
0dcd225c01

+ 15 - 0
packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts

@@ -45,6 +45,21 @@ const bar = 1
   props: propsModel,`)
   props: propsModel,`)
   })
   })
 
 
+  // #12254
+  test('w/ leading intersection type ignore', () => {
+    const { content, bindings } = compile(`<script setup lang="ts">
+type Foo = { foo: number }
+type Bar = { bar: boolean }
+defineProps</* @vue-ignore */ Foo & Bar>()
+</script>`)
+
+    expect(content).not.toMatch(`foo: { type`)
+    expect(content).toMatch(`bar: { type: Boolean, required: true }`)
+    expect(bindings).toStrictEqual({
+      bar: BindingTypes.PROPS,
+    })
+  })
+
   // #4764
   // #4764
   test('w/ leading code', () => {
   test('w/ leading code', () => {
     const { content } = compile(`
     const { content } = compile(`

+ 24 - 0
packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts

@@ -153,6 +153,30 @@ describe('resolveType', () => {
     })
     })
   })
   })
 
 
+  test('leading intersection type with ignore', () => {
+    expect(
+      resolve(`
+    type Foo = { foo: number }
+    type Bar = { bar: boolean }
+    defineProps</* @vue-ignore */ Foo & Bar>()
+    `).props,
+    ).toStrictEqual({
+      bar: ['Boolean'],
+    })
+  })
+
+  test('leading union type with ignore', () => {
+    expect(
+      resolve(`
+    type Foo = { foo: number }
+    type Bar = { bar: boolean }
+    defineProps</* @vue-ignore */ Foo | Bar>()
+    `).props,
+    ).toStrictEqual({
+      bar: ['Boolean'],
+    })
+  })
+
   test('TSPropertySignature with ignore', () => {
   test('TSPropertySignature with ignore', () => {
     expect(
     expect(
       resolve(`
       resolve(`

+ 24 - 4
packages/compiler-sfc/src/script/resolveType.ts

@@ -191,10 +191,23 @@ function innerResolveTypeElements(
   scope: TypeScope,
   scope: TypeScope,
   typeParameters?: Record<string, Node>,
   typeParameters?: Record<string, Node>,
 ): ResolvedElements {
 ): ResolvedElements {
-  if (
-    node.leadingComments &&
-    node.leadingComments.some(c => c.value.includes('@vue-ignore'))
-  ) {
+  if (hasVueIgnore(node)) {
+    if (
+      (node.type === 'TSIntersectionType' || node.type === 'TSUnionType') &&
+      node.types.length > 1
+    ) {
+      // Babel attaches comments before the first member to the parent node.
+      // Treat them as applying to the first member only.
+      return mergeElements(
+        [
+          { props: {} },
+          ...node.types
+            .slice(1)
+            .map(t => resolveTypeElements(ctx, t, scope, typeParameters)),
+        ],
+        node.type,
+      )
+    }
     return { props: {} }
     return { props: {} }
   }
   }
   switch (node.type) {
   switch (node.type) {
@@ -379,6 +392,13 @@ function typeElementsToMap(
   return res
   return res
 }
 }
 
 
+function hasVueIgnore(node: Node): boolean {
+  return !!(
+    node.leadingComments &&
+    node.leadingComments.some(c => c.value.includes('@vue-ignore'))
+  )
+}
+
 function mergeElements(
 function mergeElements(
   maps: ResolvedElements[],
   maps: ResolvedElements[],
   type: 'TSUnionType' | 'TSIntersectionType',
   type: 'TSUnionType' | 'TSIntersectionType',