Skip to content

Commit fab9c72

Browse files
committed
fix(compiler-sfc): fix type import from path aliased vue file
close #8348
1 parent 8ec73a3 commit fab9c72

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

Diff for: packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,34 @@ describe('resolveType', () => {
685685
expect(deps && [...deps]).toStrictEqual(['/user.ts'])
686686
})
687687

688+
test('ts module resolve w/ path aliased vue file', () => {
689+
const files = {
690+
'/tsconfig.json': JSON.stringify({
691+
compilerOptions: {
692+
include: ['**/*.ts', '**/*.vue'],
693+
paths: {
694+
'@/*': ['./src/*']
695+
}
696+
}
697+
}),
698+
'/src/Foo.vue':
699+
'<script lang="ts">export type P = { bar: string }</script>'
700+
}
701+
702+
const { props, deps } = resolve(
703+
`
704+
import { P } from '@/Foo.vue'
705+
defineProps<P>()
706+
`,
707+
files
708+
)
709+
710+
expect(props).toStrictEqual({
711+
bar: ['String']
712+
})
713+
expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])
714+
})
715+
688716
test('global types', () => {
689717
const files = {
690718
// ambient

Diff for: packages/compiler-sfc/src/script/context.ts

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export class ScriptCompileContext {
7070
*/
7171
deps?: Set<string>
7272

73+
/**
74+
* cache for resolved fs
75+
*/
76+
fs?: NonNullable<SFCScriptCompileOptions['fs']>
77+
7378
constructor(
7479
public descriptor: SFCDescriptor,
7580
public options: Partial<SFCScriptCompileOptions>

Diff for: packages/compiler-sfc/src/script/resolveType.ts

+36-6
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ export type SimpleTypeResolveContext = Pick<
6262
// required
6363
'source' | 'filename' | 'error' | 'options'
6464
> &
65-
Partial<Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps'>> & {
65+
Partial<
66+
Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps' | 'fs'>
67+
> & {
6668
ast: Statement[]
6769
}
6870

@@ -693,7 +695,7 @@ function qualifiedNameToPath(node: Identifier | TSQualifiedName): string[] {
693695

694696
function resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined {
695697
if (ctx.options.globalTypeFiles) {
696-
const fs: FS = ctx.options.fs || ts?.sys
698+
const fs = resolveFS(ctx)
697699
if (!fs) {
698700
throw new Error('[vue/compiler-sfc] globalTypeFiles requires fs access.')
699701
}
@@ -714,6 +716,30 @@ export function registerTS(_ts: any) {
714716

715717
type FS = NonNullable<SFCScriptCompileOptions['fs']>
716718

719+
function resolveFS(ctx: TypeResolveContext): FS | undefined {
720+
if (ctx.fs) {
721+
return ctx.fs
722+
}
723+
const fs = ctx.options.fs || ts.sys
724+
if (!fs) {
725+
return
726+
}
727+
return (ctx.fs = {
728+
fileExists(file) {
729+
if (file.endsWith('.vue.ts')) {
730+
file = file.replace(/\.ts$/, '')
731+
}
732+
return fs.fileExists(file)
733+
},
734+
readFile(file) {
735+
if (file.endsWith('.vue.ts')) {
736+
file = file.replace(/\.ts$/, '')
737+
}
738+
return fs.readFile(file)
739+
}
740+
})
741+
}
742+
717743
function resolveTypeFromImport(
718744
ctx: TypeResolveContext,
719745
node: ReferenceTypes,
@@ -731,9 +757,9 @@ function importSourceToScope(
731757
scope: TypeScope,
732758
source: string
733759
): TypeScope {
734-
const fs: FS = ctx.options.fs || ts?.sys
760+
const fs = resolveFS(ctx)
735761
if (!fs) {
736-
ctx.error(
762+
return ctx.error(
737763
`No fs option provided to \`compileScript\` in non-Node environment. ` +
738764
`File system access is required for resolving imported types.`,
739765
node,
@@ -881,7 +907,11 @@ function resolveWithTS(
881907
)
882908

883909
if (res.resolvedModule) {
884-
return res.resolvedModule.resolvedFileName
910+
let filename = res.resolvedModule.resolvedFileName
911+
if (filename.endsWith('.vue.ts')) {
912+
filename = filename.replace(/\.ts$/, '')
913+
}
914+
return filename
885915
}
886916
}
887917

@@ -936,7 +966,7 @@ export function fileToScope(
936966
return cached
937967
}
938968
// fs should be guaranteed to exist here
939-
const fs = ctx.options.fs || ts?.sys
969+
const fs = resolveFS(ctx)!
940970
const source = fs.readFile(filename) || ''
941971
const body = parseFile(filename, source, ctx.options.babelParserPlugins)
942972
const scope = new TypeScope(filename, source, 0, recordImports(body))

0 commit comments

Comments
 (0)