Skip to content

Commit 401f4ed

Browse files
committed
fix(compiler-sfc): resolve type re-exports inside declare global
1 parent 3310eea commit 401f4ed

2 files changed

Lines changed: 73 additions & 3 deletions

File tree

packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,42 @@ describe('resolveType', () => {
14971497
})
14981498
})
14991499

1500+
test('global types with re-exports', () => {
1501+
const files = {
1502+
'/foo.ts': `export interface Foo { foo: number }`,
1503+
'/bar.ts': `export interface Bar { bar: boolean }`,
1504+
'/baz.ts': `export interface Baz { baz: string }`,
1505+
'/global.d.ts': `
1506+
declare global {
1507+
export type { Foo } from './foo'
1508+
export { Bar } from './bar'
1509+
export * from './baz'
1510+
}
1511+
export {}
1512+
`,
1513+
}
1514+
1515+
const globalTypeFiles = { globalTypeFiles: ['/global.d.ts'] }
1516+
1517+
expect(
1518+
resolve(`defineProps<Foo>()`, files, globalTypeFiles).props,
1519+
).toStrictEqual({
1520+
foo: ['Number'],
1521+
})
1522+
1523+
expect(
1524+
resolve(`defineProps<Bar>()`, files, globalTypeFiles).props,
1525+
).toStrictEqual({
1526+
bar: ['Boolean'],
1527+
})
1528+
1529+
expect(
1530+
resolve(`defineProps<Baz>()`, files, globalTypeFiles).props,
1531+
).toStrictEqual({
1532+
baz: ['String'],
1533+
})
1534+
})
1535+
15001536
test('global types with ambient references', () => {
15011537
const files = {
15021538
// with references

packages/compiler-sfc/src/script/resolveType.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,9 +1337,43 @@ function recordTypes(
13371337
}
13381338
} else if (stmt.type === 'TSModuleDeclaration' && stmt.global) {
13391339
for (const s of (stmt.body as TSModuleBlock).body) {
1340-
if (s.type === 'ExportNamedDeclaration' && s.declaration) {
1341-
// Handle export declarations inside declare global
1342-
recordType(s.declaration, types, declares)
1340+
if (s.type === 'ExportNamedDeclaration') {
1341+
if (s.declaration) {
1342+
// Handle export declarations inside declare global
1343+
recordType(s.declaration, types, declares)
1344+
} else if (s.source) {
1345+
// Handle re-exports inside declare global, e.g.
1346+
// `export type { Foo } from './foo'`. Global lookup only checks
1347+
// `types`/`declares`, so resolve the source eagerly.
1348+
const sourceScope = importSourceToScope(
1349+
ctx,
1350+
s.source,
1351+
scope,
1352+
s.source.value,
1353+
)
1354+
for (const spec of s.specifiers) {
1355+
if (spec.type === 'ExportSpecifier') {
1356+
const exported = getId(spec.exported)
1357+
const local = spec.local.name
1358+
if (sourceScope.exportedTypes[local]) {
1359+
types[exported] = sourceScope.exportedTypes[local]
1360+
}
1361+
if (sourceScope.exportedDeclares[local]) {
1362+
declares[exported] = sourceScope.exportedDeclares[local]
1363+
}
1364+
}
1365+
}
1366+
}
1367+
} else if (s.type === 'ExportAllDeclaration' && s.source) {
1368+
// Handle `export * from './foo'` inside declare global
1369+
const sourceScope = importSourceToScope(
1370+
ctx,
1371+
s.source,
1372+
scope,
1373+
s.source.value,
1374+
)
1375+
Object.assign(types, sourceScope.exportedTypes)
1376+
Object.assign(declares, sourceScope.exportedDeclares)
13431377
} else {
13441378
recordType(s, types, declares)
13451379
}

0 commit comments

Comments
 (0)