Jelajahi Sumber

fix(compiler-sfc): improved type resolution for function type aliases (#13452)

close #13444
Tycho 10 bulan lalu
induk
melakukan
f3479aac96

+ 0 - 21
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap

@@ -148,27 +148,6 @@ export default /*@__PURE__*/_defineComponent({
 
       
     
-return {  }
-}
-
-})"
-`;
-
-exports[`defineProps > w/ TSTypeAliasDeclaration 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-type FunFoo<O> = (item: O) => boolean;
-    type FunBar = FunFoo<number>;
-    
-export default /*@__PURE__*/_defineComponent({
-  props: {
-    foo: { type: Function, required: false, default: () => true },
-    bar: { type: Function, required: false, default: () => true }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-    
-    
 return {  }
 }
 

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

@@ -808,30 +808,4 @@ const props = defineProps({ foo: String })
     expect(content).toMatch(`foo: { default: 5.5, type: Number }`)
     assertCode(content)
   })
-
-  test('w/ TSTypeAliasDeclaration', () => {
-    const { content } = compile(`
-    <script setup lang="ts">
-    type FunFoo<O> = (item: O) => boolean;
-    type FunBar = FunFoo<number>;
-    withDefaults(
-      defineProps<{
-        foo?: FunFoo<number>;
-        bar?: FunBar;
-      }>(),
-      {
-        foo: () => true,
-        bar: () => true,
-      },
-    );
-    </script>
-      `)
-    assertCode(content)
-    expect(content).toMatch(
-      `foo: { type: Function, required: false, default: () => true }`,
-    )
-    expect(content).toMatch(
-      `bar: { type: Function, required: false, default: () => true }`,
-    )
-  })
 })

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

@@ -731,6 +731,38 @@ describe('resolveType', () => {
     })
   })
 
+  describe('type alias declaration', () => {
+    // #13240
+    test('function type', () => {
+      expect(
+        resolve(`
+      type FunFoo<O> = (item: O) => boolean;
+      type FunBar = FunFoo<number>;
+      defineProps<{
+        foo?: FunFoo<number>;
+        bar?: FunBar;
+      }>()
+      `).props,
+      ).toStrictEqual({
+        foo: ['Function'],
+        bar: ['Function'],
+      })
+    })
+
+    test('fallback to Unknown', () => {
+      expect(
+        resolve(`
+      type Brand<T> = T & {};
+      defineProps<{
+        foo: Brand<string>;
+      }>()
+      `).props,
+      ).toStrictEqual({
+        foo: [UNKNOWN_TYPE],
+      })
+    })
+  })
+
   describe('generics', () => {
     test('generic with type literal', () => {
       expect(

+ 8 - 7
packages/compiler-sfc/src/script/resolveType.ts

@@ -1588,13 +1588,14 @@ export function inferRuntimeType(
       case 'TSTypeReference': {
         const resolved = resolveTypeReference(ctx, node, scope)
         if (resolved) {
-          if (resolved.type === 'TSTypeAliasDeclaration') {
-            return inferRuntimeType(
-              ctx,
-              resolved.typeAnnotation,
-              resolved._ownerScope,
-              isKeyOf,
-            )
+          // #13240
+          // Special case for function type aliases to ensure correct runtime behavior
+          // other type aliases still fallback to unknown as before
+          if (
+            resolved.type === 'TSTypeAliasDeclaration' &&
+            resolved.typeAnnotation.type === 'TSFunctionType'
+          ) {
+            return ['Function']
           }
           return inferRuntimeType(ctx, resolved, resolved._ownerScope, isKeyOf)
         }