From 49299742ace19836f27f9b315789b0188238b438 Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 18 Jun 2025 11:36:29 +0800 Subject: [PATCH 1/4] feat(compiler-sfc): support ${configDir} in paths for TypeScript 5.5+ --- packages/compiler-sfc/src/script/resolveType.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 85832dfc39a..60b23ca8a63 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -1029,6 +1029,13 @@ function resolveWithTS( if (configs.length === 1) { matchedConfig = configs[0] } else { + const [major, minor] = ts.versionMajorMinor.split('.').map(Number) + function getPattern(base: string, p: string): string { + return p.startsWith('${configDir}') && major >= 5 && minor >= 5 + ? // ts 5.5+ supports ${configDir} in paths + p.replace('${configDir}', dirname(configPath!)) + : joinPaths(base, p) + } // resolve which config matches the current file for (const c of configs) { const base = normalizePath( @@ -1039,11 +1046,11 @@ function resolveWithTS( const excluded: string[] | undefined = c.config.raw?.exclude if ( (!included && (!base || containingFile.startsWith(base))) || - included?.some(p => isMatch(containingFile, joinPaths(base, p))) + included?.some(p => isMatch(containingFile, getPattern(base, p))) ) { if ( excluded && - excluded.some(p => isMatch(containingFile, joinPaths(base, p))) + excluded.some(p => isMatch(containingFile, getPattern(base, p))) ) { continue } From 5fab826ea20b867d950adce7d7a55c027ea6f7e4 Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 18 Jun 2025 14:38:59 +0800 Subject: [PATCH 2/4] test: add test --- .../compileScript/resolveType.spec.ts | 39 +++++++++++++++++++ .../compiler-sfc/src/script/resolveType.ts | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index 68fc5cc3159..6b4770ecb7d 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -1155,6 +1155,45 @@ describe('resolveType', () => { expect(deps && [...deps]).toStrictEqual(['/user.ts']) }) + // #13484 + test('ts module resolve w/ project reference & extends & ${configDir}', () => { + const files = { + '/tsconfig.json': JSON.stringify({ + files: [], + references: [{ path: './tsconfig.app.json' }], + }), + '/tsconfig.app.json': JSON.stringify({ + extends: ['./tsconfigs/base.json'], + }), + '/tsconfigs/base.json': JSON.stringify({ + compilerOptions: { + paths: { + '@/*': ['${configDir}/src/*'], + }, + }, + include: ['${configDir}/src/**/*.ts', '${configDir}/src/**/*.vue'], + }), + '/src/types.ts': + 'export type BaseProps = { foo?: string, bar?: string }', + } + + const { props, deps } = resolve( + ` + import { BaseProps } from '@/types.ts'; + defineProps() + `, + files, + {}, + '/src/components/Foo.vue', + ) + + expect(props).toStrictEqual({ + foo: ['String'], + bar: ['String'], + }) + expect(deps && [...deps]).toStrictEqual(['/src/types.ts']) + }) + test('ts module resolve w/ project reference folder', () => { const files = { '/tsconfig.json': JSON.stringify({ diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 60b23ca8a63..9e518418b4d 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -1033,7 +1033,7 @@ function resolveWithTS( function getPattern(base: string, p: string): string { return p.startsWith('${configDir}') && major >= 5 && minor >= 5 ? // ts 5.5+ supports ${configDir} in paths - p.replace('${configDir}', dirname(configPath!)) + normalizePath(p.replace('${configDir}', dirname(configPath!))) : joinPaths(base, p) } // resolve which config matches the current file From 5246bdfe53df73ba0ecdfff75c46780e02e49099 Mon Sep 17 00:00:00 2001 From: edison Date: Wed, 18 Jun 2025 14:46:26 +0800 Subject: [PATCH 3/4] Update packages/compiler-sfc/src/script/resolveType.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- packages/compiler-sfc/src/script/resolveType.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 9e518418b4d..63ef30b3a49 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -1031,7 +1031,9 @@ function resolveWithTS( } else { const [major, minor] = ts.versionMajorMinor.split('.').map(Number) function getPattern(base: string, p: string): string { - return p.startsWith('${configDir}') && major >= 5 && minor >= 5 + const supportsConfigDir = + major > 5 || (major === 5 && minor >= 5) + return p.startsWith('${configDir}') && supportsConfigDir ? // ts 5.5+ supports ${configDir} in paths normalizePath(p.replace('${configDir}', dirname(configPath!))) : joinPaths(base, p) From 7588b4dacf309c1853937df3eebc995826ffee36 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 06:47:11 +0000 Subject: [PATCH 4/4] chore: update --- packages/compiler-sfc/src/script/resolveType.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 63ef30b3a49..ae7bcbfe170 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -1030,12 +1030,11 @@ function resolveWithTS( matchedConfig = configs[0] } else { const [major, minor] = ts.versionMajorMinor.split('.').map(Number) - function getPattern(base: string, p: string): string { - const supportsConfigDir = - major > 5 || (major === 5 && minor >= 5) + const getPattern = (base: string, p: string) => { + // ts 5.5+ supports ${configDir} in paths + const supportsConfigDir = major > 5 || (major === 5 && minor >= 5) return p.startsWith('${configDir}') && supportsConfigDir - ? // ts 5.5+ supports ${configDir} in paths - normalizePath(p.replace('${configDir}', dirname(configPath!))) + ? normalizePath(p.replace('${configDir}', dirname(configPath!))) : joinPaths(base, p) } // resolve which config matches the current file