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

close #13444
This commit is contained in:
Tycho 2025-06-18 20:54:09 +08:00 committed by GitHub
parent 919c44744b
commit f3479aac96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 54 deletions

View File

@ -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 { }
}

View File

@ -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 }`,
)
})
})

View File

@ -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(

View File

@ -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)
}