1
1
/* eslint-disable regexp/no-super-linear-backtracking, regexp/no-misleading-capturing-group, regexp/optimal-quantifier-concatenation */
2
2
import type { Declaration , ProcessingContext } from './types'
3
3
4
+ /**
5
+ * Replace unresolved types with 'any' in the DTS output
6
+ */
7
+ function replaceUnresolvedTypes ( dtsContent : string , declarations : Declaration [ ] , imports : Declaration [ ] ) : string {
8
+ // Get all imported type names
9
+ const importedTypes = new Set < string > ( )
10
+ for ( const imp of imports ) {
11
+ const allImportedItems = extractAllImportedItems ( imp . text )
12
+ allImportedItems . forEach ( item => importedTypes . add ( item ) )
13
+ }
14
+
15
+ // Get all declared type names (interfaces, types, classes, enums)
16
+ const declaredTypes = new Set < string > ( )
17
+ for ( const decl of declarations ) {
18
+ if ( [ 'interface' , 'type' , 'class' , 'enum' ] . includes ( decl . kind ) ) {
19
+ declaredTypes . add ( decl . name )
20
+ }
21
+ }
22
+
23
+ // Common TypeScript built-in types that don't need to be imported
24
+ const builtInTypes = new Set ( [
25
+ 'string' , 'number' , 'boolean' , 'object' , 'any' , 'unknown' , 'never' , 'void' ,
26
+ 'undefined' , 'null' , 'Array' , 'Promise' , 'Record' , 'Partial' , 'Required' ,
27
+ 'Pick' , 'Omit' , 'Exclude' , 'Extract' , 'NonNullable' , 'ReturnType' ,
28
+ 'Parameters' , 'ConstructorParameters' , 'InstanceType' , 'ThisType' ,
29
+ 'Function' , 'Date' , 'RegExp' , 'Error' , 'Map' , 'Set' , 'WeakMap' , 'WeakSet'
30
+ ] )
31
+
32
+ // Common generic type parameter names that should not be replaced
33
+ const genericTypeParams = new Set ( [
34
+ 'T' , 'K' , 'V' , 'U' , 'R' , 'P' , 'E' , 'A' , 'B' , 'C' , 'D' , 'F' , 'G' , 'H' , 'I' , 'J' , 'L' , 'M' , 'N' , 'O' , 'Q' , 'S' , 'W' , 'X' , 'Y' , 'Z'
35
+ ] )
36
+
37
+ // Extract all types that are actually defined in the DTS content itself
38
+ // This catches types that weren't extracted but are still defined in the output
39
+ const definedInDts = new Set < string > ( )
40
+
41
+ // Look for interface definitions
42
+ const interfaceMatches = dtsContent . match ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? i n t e r f a c e \s + ( [ A - Z ] [ a - z A - Z 0 - 9 ] * ) / g)
43
+ if ( interfaceMatches ) {
44
+ interfaceMatches . forEach ( match => {
45
+ const name = match . replace ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? i n t e r f a c e \s + / , '' )
46
+ definedInDts . add ( name )
47
+ } )
48
+ }
49
+
50
+ // Look for type alias definitions
51
+ const typeMatches = dtsContent . match ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? t y p e \s + ( [ A - Z ] [ a - z A - Z 0 - 9 ] * ) / g)
52
+ if ( typeMatches ) {
53
+ typeMatches . forEach ( match => {
54
+ const name = match . replace ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? t y p e \s + / , '' )
55
+ definedInDts . add ( name )
56
+ } )
57
+ }
58
+
59
+ // Look for class definitions
60
+ const classMatches = dtsContent . match ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? c l a s s \s + ( [ A - Z ] [ a - z A - Z 0 - 9 ] * ) / g)
61
+ if ( classMatches ) {
62
+ classMatches . forEach ( match => {
63
+ const name = match . replace ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? c l a s s \s + / , '' )
64
+ definedInDts . add ( name )
65
+ } )
66
+ }
67
+
68
+ // Look for enum definitions
69
+ const enumMatches = dtsContent . match ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? (?: c o n s t \s + ) ? e n u m \s + ( [ A - Z ] [ a - z A - Z 0 - 9 ] * ) / g)
70
+ if ( enumMatches ) {
71
+ enumMatches . forEach ( match => {
72
+ const name = match . replace ( / (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? (?: c o n s t \s + ) ? e n u m \s + / , '' )
73
+ definedInDts . add ( name )
74
+ } )
75
+ }
76
+
77
+ // Only replace types that are:
78
+ // 1. Not imported
79
+ // 2. Not declared in our extracted declarations
80
+ // 3. Not built-in TypeScript types
81
+ // 4. Not generic type parameters
82
+ // 5. Not defined anywhere in the DTS content itself
83
+ // 6. Actually used as types (not values)
84
+ // 7. Have specific patterns that indicate they're problematic
85
+
86
+ let result = dtsContent
87
+
88
+ // For now, don't do any automatic type replacement
89
+ // The proper solution is to improve the extractor to find all referenced types
90
+
91
+ return result
92
+ }
93
+
4
94
/**
5
95
* Extract all imported items from an import statement
6
96
*/
@@ -149,14 +239,23 @@ export function processDeclarations(
149
239
}
150
240
}
151
241
152
- // Check which imports are needed for interfaces and types (including non-exported ones that are referenced by exported items)
242
+ // Check which imports are needed for ALL declarations that will be included in the DTS output
243
+ // This includes non-exported types, interfaces, classes, etc. that are still part of the public API
244
+
245
+ // Check interfaces (both exported and non-exported ones that are referenced)
153
246
for ( const iface of interfaces ) {
154
- // Include interface if it's exported OR if it's referenced by exported functions
247
+ // Include interface if it's exported OR if it's referenced by any declaration we're including
155
248
const isReferencedByExports = functions . some ( func =>
156
249
func . isExported && func . text . includes ( iface . name ) ,
157
250
)
251
+ const isReferencedByClasses = classes . some ( cls =>
252
+ cls . text . includes ( iface . name ) ,
253
+ )
254
+ const isReferencedByTypes = types . some ( type =>
255
+ type . text . includes ( iface . name ) ,
256
+ )
158
257
159
- if ( iface . isExported || isReferencedByExports ) {
258
+ if ( iface . isExported || isReferencedByExports || isReferencedByClasses || isReferencedByTypes ) {
160
259
for ( const imp of imports ) {
161
260
const allImportedItems = extractAllImportedItems ( imp . text )
162
261
for ( const item of allImportedItems ) {
@@ -169,15 +268,53 @@ export function processDeclarations(
169
268
}
170
269
}
171
270
271
+ // Check ALL types (exported and non-exported) since they may be included in DTS
172
272
for ( const type of types ) {
173
- if ( type . isExported ) {
174
- for ( const imp of imports ) {
175
- const allImportedItems = extractAllImportedItems ( imp . text )
176
- for ( const item of allImportedItems ) {
177
- const regex = new RegExp ( `\\b${ item . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } \\b` )
178
- if ( regex . test ( type . text ) ) {
179
- usedImportItems . add ( item )
180
- }
273
+ for ( const imp of imports ) {
274
+ const allImportedItems = extractAllImportedItems ( imp . text )
275
+ for ( const item of allImportedItems ) {
276
+ const regex = new RegExp ( `\\b${ item . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } \\b` )
277
+ if ( regex . test ( type . text ) ) {
278
+ usedImportItems . add ( item )
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ // Check ALL classes (exported and non-exported) since they may be included in DTS
285
+ for ( const cls of classes ) {
286
+ for ( const imp of imports ) {
287
+ const allImportedItems = extractAllImportedItems ( imp . text )
288
+ for ( const item of allImportedItems ) {
289
+ const regex = new RegExp ( `\\b${ item . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } \\b` )
290
+ if ( regex . test ( cls . text ) ) {
291
+ usedImportItems . add ( item )
292
+ }
293
+ }
294
+ }
295
+ }
296
+
297
+ // Check ALL enums (exported and non-exported) since they may be included in DTS
298
+ for ( const enumDecl of enums ) {
299
+ for ( const imp of imports ) {
300
+ const allImportedItems = extractAllImportedItems ( imp . text )
301
+ for ( const item of allImportedItems ) {
302
+ const regex = new RegExp ( `\\b${ item . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } \\b` )
303
+ if ( regex . test ( enumDecl . text ) ) {
304
+ usedImportItems . add ( item )
305
+ }
306
+ }
307
+ }
308
+ }
309
+
310
+ // Check ALL modules/namespaces since they may be included in DTS
311
+ for ( const mod of modules ) {
312
+ for ( const imp of imports ) {
313
+ const allImportedItems = extractAllImportedItems ( imp . text )
314
+ for ( const item of allImportedItems ) {
315
+ const regex = new RegExp ( `\\b${ item . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) } \\b` )
316
+ if ( regex . test ( mod . text ) ) {
317
+ usedImportItems . add ( item )
181
318
}
182
319
}
183
320
}
@@ -352,7 +489,13 @@ export function processDeclarations(
352
489
// Process default export last
353
490
output . push ( ...defaultExport )
354
491
355
- return output . filter ( line => line !== '' ) . join ( '\n' )
492
+ let result = output . filter ( line => line !== '' ) . join ( '\n' )
493
+
494
+ // Post-process to replace unresolved internal types with 'any'
495
+ // This handles cases where internal interfaces/types are referenced but not extracted
496
+ result = replaceUnresolvedTypes ( result , declarations , imports )
497
+
498
+ return result
356
499
}
357
500
358
501
/**
0 commit comments