@@ -40,6 +40,13 @@ export interface RegexPatterns {
40
40
readonly exportCleanup : RegExp
41
41
/** Default export */
42
42
readonly defaultExport : RegExp
43
+
44
+ readonly complexType : RegExp
45
+ readonly unionIntersection : RegExp
46
+ readonly mappedType : RegExp
47
+ readonly conditionalType : RegExp
48
+ readonly genericConstraints : RegExp
49
+ readonly functionOverload : RegExp
43
50
}
44
51
45
52
/**
@@ -79,6 +86,14 @@ export const REGEX: RegexPatterns = {
79
86
// Export patterns
80
87
exportCleanup : / ^ e x p o r t \s + d e f a u l t \s + / ,
81
88
defaultExport : / e x p o r t \s + d e f a u l t \s + / ,
89
+
90
+ // New patterns for complex types
91
+ complexType : / t y p e \s + ( [ ^ = < ] + ) (?: < [ ^ > ] + > ) ? \s * = \s * ( [ ^ ; ] + ) / ,
92
+ unionIntersection : / ( [ ^ | & ] + ) (?: \s * [ | & ] \s * ( [ ^ | & ] + ) ) + / ,
93
+ mappedType : / \{ \s * \[ \s * ( [ ^ \] ] + ) \s * i n \s * ( [ ^ \] ] + ) \s * \] : / ,
94
+ conditionalType : / ( [ ^ e x t n d s ] + ) \s + e x t e n d s \s + ( [ ^ ? ] + ) \s * \? \s * ( [ ^ : ] + ) \s * : \s * ( [ ^ ; ] + ) / ,
95
+ genericConstraints : / < ( [ ^ > ] + ) > / ,
96
+ functionOverload : / ^ (?: e x p o r t \s + ) ? (?: d e c l a r e \s + ) ? f u n c t i o n \s + ( [ ^ ( < \s ] + ) / ,
82
97
} as const satisfies RegexPatterns
83
98
84
99
/**
@@ -416,11 +431,12 @@ export function processImports(imports: string[], usedTypes: Set<string>): strin
416
431
}
417
432
418
433
/**
419
- * Process declarations with type inference
434
+ * Process declarations
420
435
*/
421
436
export function processDeclaration ( declaration : string , state : ProcessingState ) : string {
422
437
const trimmed = declaration . trim ( )
423
438
439
+ // Handle different declaration types with proper formatting
424
440
if ( trimmed . startsWith ( 'export const' ) ) {
425
441
return processConstDeclaration ( trimmed )
426
442
}
@@ -451,7 +467,7 @@ export function processDeclaration(declaration: string, state: ProcessingState):
451
467
452
468
if ( trimmed . startsWith ( 'export function' ) || trimmed . startsWith ( 'export async function' ) ) {
453
469
const processed = trimmed . replace ( / \b a s y n c \s + / , '' )
454
- return processFunctionDeclaration ( processed , state . usedTypes )
470
+ return processFunctionDeclaration ( processed , state . usedTypes , true )
455
471
}
456
472
457
473
if ( trimmed . startsWith ( 'function' ) || trimmed . startsWith ( 'async function' ) ) {
@@ -607,6 +623,60 @@ export function processCompleteProperty({ key, content }: { key?: string, conten
607
623
return processSimpleValue ( key , valueContent )
608
624
}
609
625
626
+ /**
627
+ * Process complex type declarations
628
+ */
629
+ function processComplexTypeDeclaration ( declaration : string ) : string {
630
+ // Handle union and intersection types
631
+ if ( declaration . includes ( '|' ) || declaration . includes ( '&' ) ) {
632
+ const match = declaration . match ( REGEX . unionIntersection )
633
+ if ( match ) {
634
+ const types = declaration . split ( / \s * [ | & ] \s * / )
635
+ return types . join ( declaration . includes ( '|' ) ? ' | ' : ' & ' )
636
+ }
637
+ }
638
+
639
+ // Handle mapped types
640
+ if ( declaration . includes ( '[' ) && declaration . includes ( 'in' ) ) {
641
+ const match = declaration . match ( REGEX . mappedType )
642
+ if ( match ) {
643
+ const [ , keyType , valueType ] = match
644
+ return `{ [${ keyType } in ${ valueType } ]: ${ processTypeExpression ( valueType ) } }`
645
+ }
646
+ }
647
+
648
+ // Handle conditional types
649
+ if ( declaration . includes ( 'extends' ) && declaration . includes ( '?' ) ) {
650
+ const match = declaration . match ( REGEX . conditionalType )
651
+ if ( match ) {
652
+ const [ , condition , constraint , trueType , falseType ] = match
653
+ return `${ condition } extends ${ constraint } ? ${ trueType } : ${ falseType } `
654
+ }
655
+ }
656
+
657
+ return declaration
658
+ }
659
+
660
+ /**
661
+ * Process type expressions
662
+ */
663
+ function processTypeExpression ( expression : string ) : string {
664
+ // Handle generics
665
+ if ( expression . includes ( '<' ) ) {
666
+ const match = expression . match ( REGEX . genericConstraints )
667
+ if ( match ) {
668
+ const [ fullMatch , constraints ] = match
669
+ const processedConstraints = constraints . split ( ',' ) . map ( ( c ) => {
670
+ const [ name , constraint ] = c . split ( 'extends' ) . map ( s => s . trim ( ) )
671
+ return constraint ? `${ name } extends ${ constraint } ` : name
672
+ } )
673
+ return expression . replace ( fullMatch , `<${ processedConstraints . join ( ', ' ) } >` )
674
+ }
675
+ }
676
+
677
+ return expression
678
+ }
679
+
610
680
/**
611
681
* Extract nested content between delimiters
612
682
*/
@@ -699,6 +769,36 @@ function inferArrayType(value: string): string {
699
769
return `Array<${ uniqueTypes . join ( ' | ' ) } >`
700
770
}
701
771
772
+ /**
773
+ * Enhanced type inference for complex cases
774
+ */
775
+ export function inferComplexType ( value : string ) : string {
776
+ const trimmed = value . trim ( )
777
+
778
+ if ( trimmed . includes ( '=>' ) ) {
779
+ return inferFunctionType ( trimmed )
780
+ }
781
+
782
+ if ( trimmed . startsWith ( '[' ) ) {
783
+ return inferArrayType ( trimmed )
784
+ }
785
+
786
+ if ( trimmed . startsWith ( '{' ) ) {
787
+ return processObjectLiteral ( trimmed )
788
+ }
789
+
790
+ if ( trimmed . includes ( 'extends' ) ) {
791
+ return processComplexTypeDeclaration ( trimmed )
792
+ }
793
+
794
+ if ( trimmed . includes ( '|' ) || trimmed . includes ( '&' ) ) {
795
+ return processComplexTypeDeclaration ( trimmed )
796
+ }
797
+
798
+ // Pass through direct type references and primitives
799
+ return trimmed
800
+ }
801
+
702
802
/**
703
803
* Infer element type with improved type detection
704
804
*/
@@ -858,6 +958,14 @@ export function parseObjectLiteral(objStr: string): PropertyInfo[] {
858
958
return extractObjectProperties ( [ content ] )
859
959
}
860
960
961
+ /**
962
+ * Process object type literals
963
+ */
964
+ function processObjectLiteral ( obj : string ) : string {
965
+ const properties = extractObjectProperties ( [ obj ] )
966
+ return formatObjectType ( properties )
967
+ }
968
+
861
969
/**
862
970
* Process interface declarations
863
971
*/
@@ -879,9 +987,13 @@ export function processTypeDeclaration(declaration: string, isExported = true):
879
987
const lines = declaration . split ( '\n' )
880
988
const firstLine = lines [ 0 ]
881
989
const typeName = firstLine . split ( 'type' ) [ 1 ] . split ( '=' ) [ 0 ] . trim ( )
882
- const typeBody = firstLine . split ( '=' ) [ 1 ] ?. trim ( ) || lines . slice ( 1 ) . join ( '\n' ) . trim ( ) . replace ( / ; $ / , '' )
990
+ const typeBody = firstLine . split ( '=' ) [ 1 ] ?. trim ( )
991
+ || lines . slice ( 1 ) . join ( '\n' ) . trim ( ) . replace ( / ; $ / , '' )
992
+
993
+ // Use complex type inference for the type body
994
+ const inferredType = inferComplexType ( typeBody )
883
995
884
- return `${ isExported ? 'export ' : '' } declare type ${ typeName } = ${ typeBody } ;`
996
+ return `${ isExported ? 'export ' : '' } declare type ${ typeName } = ${ inferredType } ;`
885
997
}
886
998
887
999
/**
@@ -929,11 +1041,14 @@ export function extractFunctionSignature(declaration: string): FunctionSignature
929
1041
}
930
1042
931
1043
/**
932
- * Process function declarations
1044
+ * Process function declarations with overloads
1045
+ * @param declaration - Function declaration to process
1046
+ * @param usedTypes - Set of used types to track
1047
+ * @param isExported - Whether the function is exported
933
1048
*/
934
1049
export function processFunctionDeclaration (
935
1050
declaration : string ,
936
- usedTypes : Set < string > ,
1051
+ usedTypes ? : Set < string > ,
937
1052
isExported = true ,
938
1053
) : string {
939
1054
const {
@@ -944,7 +1059,10 @@ export function processFunctionDeclaration(
944
1059
generics,
945
1060
} = extractFunctionSignature ( declaration )
946
1061
947
- trackUsedTypes ( `${ generics } ${ params } ${ returnType } ` , usedTypes )
1062
+ // Track used types if provided
1063
+ if ( usedTypes ) {
1064
+ trackUsedTypes ( `${ generics } ${ params } ${ returnType } ` , usedTypes )
1065
+ }
948
1066
949
1067
const parts = [
950
1068
isExported ? 'export' : '' ,
@@ -1246,6 +1364,26 @@ function formatSingleDeclaration(declaration: string): string {
1246
1364
return formatted
1247
1365
}
1248
1366
1367
+ /**
1368
+ * Format function declaration
1369
+ */
1370
+ function formatFunctionDeclaration (
1371
+ signature : FunctionSignature ,
1372
+ isExported : boolean ,
1373
+ ) : string {
1374
+ const {
1375
+ name,
1376
+ params,
1377
+ returnType,
1378
+ isAsync,
1379
+ generics,
1380
+ } = signature
1381
+
1382
+ return `${ isExported ? 'export ' : '' } declare ${ isAsync ? 'async ' : '' } function ${ name } ${
1383
+ generics ? `<${ generics } >` : ''
1384
+ } (${ params } ): ${ returnType } ;`
1385
+ }
1386
+
1249
1387
/**
1250
1388
* Check if semicolon should be added
1251
1389
*/
0 commit comments