From e388f1a09fde78cf006450f060813d972ac8c23d Mon Sep 17 00:00:00 2001 From: edison Date: Wed, 24 Sep 2025 17:29:38 +0800 Subject: [PATCH] fix(compiler-sfc): enhance inferRuntimeType to support TSMappedType with indexed access (#13848) close #13847 --- .../compileScript/resolveType.spec.ts | 16 ++++++++ .../compiler-sfc/src/script/resolveType.ts | 41 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index 0f46d6085..eff2f01b9 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -742,6 +742,22 @@ describe('resolveType', () => { }) }) + test('TSMappedType with indexed access', () => { + const { props } = resolve( + ` + type Prettify = { [K in keyof T]: T[K] } & {} + type Side = 'top' | 'right' | 'bottom' | 'left' + type AlignedPlacement = \`\${Side}-\${Alignment}\` + type Alignment = 'start' | 'end' + type Placement = Prettify + defineProps<{placement?: Placement}>() + `, + ) + expect(props).toStrictEqual({ + placement: ['String', 'Object'], + }) + }) + describe('type alias declaration', () => { // #13240 test('function type', () => { diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index f6763b764..54b93b3fe 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -1788,6 +1788,47 @@ export function inferRuntimeType( typeParameters, ).filter(t => t !== UNKNOWN_TYPE) } + case 'TSMappedType': { + // only support { [K in keyof T]: T[K] } + const { typeAnnotation, typeParameter } = node + if ( + typeAnnotation && + typeAnnotation.type === 'TSIndexedAccessType' && + typeParameter && + typeParameter.constraint && + typeParameters + ) { + const constraint = typeParameter.constraint + if ( + constraint.type === 'TSTypeOperator' && + constraint.operator === 'keyof' && + constraint.typeAnnotation && + constraint.typeAnnotation.type === 'TSTypeReference' && + constraint.typeAnnotation.typeName.type === 'Identifier' + ) { + const typeName = constraint.typeAnnotation.typeName.name + const index = typeAnnotation.indexType + const obj = typeAnnotation.objectType + if ( + obj && + obj.type === 'TSTypeReference' && + obj.typeName.type === 'Identifier' && + obj.typeName.name === typeName && + index && + index.type === 'TSTypeReference' && + index.typeName.type === 'Identifier' && + index.typeName.name === typeParameter.name + ) { + const targetType = typeParameters[typeName] + if (targetType) { + return inferRuntimeType(ctx, targetType, scope) + } + } + } + } + + return [UNKNOWN_TYPE] + } case 'TSEnumDeclaration': return inferEnumType(node) -- 2.47.3