diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index eff2f01b981..557f6ec5d93 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -20,6 +20,8 @@ describe('resolveType', () => { foo: number // property bar(): void // method 'baz': string // string literal key + [\`qux\`]: boolean // template literal key + 123: symbol // numeric literal key (e: 'foo'): void // call signature (e: 'bar'): void }>()`) @@ -27,6 +29,8 @@ describe('resolveType', () => { foo: ['Number'], bar: ['Function'], baz: ['String'], + qux: ['Boolean'], + 123: ['Symbol'], }) expect(calls?.length).toBe(2) }) @@ -195,7 +199,7 @@ describe('resolveType', () => { type T = 'foo' | 'bar' type S = 'x' | 'y' defineProps<{ - [\`_\${T}_\${S}_\`]: string + [K in \`_\${T}_\${S}_\`]: string }>() `).props, ).toStrictEqual({ diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index b40c7cd7cbf..9cb4ce8e7c2 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -29,6 +29,7 @@ import { createGetCanonicalFileName, getId, getImportedName, + getStringLiteralKey, joinPaths, normalizePath, } from './utils' @@ -336,13 +337,9 @@ function typeElementsToMap( Object.assign(scope.types, typeParameters) } ;(e as MaybeWithScope)._ownerScope = scope - const name = getId(e.key) - if (name && !e.computed) { + const name = getStringLiteralKey(e) + if (name !== null) { res.props[name] = e as ResolvedElements['props'][string] - } else if (e.key.type === 'TemplateLiteral') { - for (const key of resolveTemplateKeys(ctx, e.key, scope)) { - res.props[key] = e as ResolvedElements['props'][string] - } } else { ctx.error( `Unsupported computed key in type referenced by a macro`, @@ -2029,8 +2026,7 @@ function findStaticPropertyType(node: TSTypeLiteral, key: string) { const prop = node.members.find( m => m.type === 'TSPropertySignature' && - !m.computed && - getId(m.key) === key && + getStringLiteralKey(m) === key && m.typeAnnotation, ) return prop && prop.typeAnnotation!.typeAnnotation diff --git a/packages/compiler-sfc/src/script/utils.ts b/packages/compiler-sfc/src/script/utils.ts index 1b7da0e3497..bda64dc2e41 100644 --- a/packages/compiler-sfc/src/script/utils.ts +++ b/packages/compiler-sfc/src/script/utils.ts @@ -7,6 +7,8 @@ import type { ImportSpecifier, Node, StringLiteral, + TSMethodSignature, + TSPropertySignature, } from '@babel/types' import path from 'path' @@ -79,6 +81,22 @@ export function getId(node: Expression) { : null } +export function getStringLiteralKey( + node: TSPropertySignature | TSMethodSignature, +): string | null { + return node.computed + ? node.key.type === 'TemplateLiteral' && !node.key.expressions.length + ? node.key.quasis.map(q => q.value.cooked).join('') + : null + : node.key.type === 'Identifier' + ? node.key.name + : node.key.type === 'StringLiteral' + ? node.key.value + : node.key.type === 'NumericLiteral' + ? String(node.key.value) + : null +} + const identity = (str: string) => str const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g const toLowerCase = (str: string) => str.toLowerCase()