@@ -354,6 +354,35 @@ export function processFunctionDeclaration(decl: Declaration): string {
354354 return decl . text
355355}
356356
357+ /**
358+ * Check if a type annotation is a generic/broad type that should be replaced with narrow inference
359+ */
360+ function isGenericType ( typeAnnotation : string ) : boolean {
361+ const trimmed = typeAnnotation . trim ( )
362+
363+ // Generic types that are less specific than narrow inference
364+ if ( trimmed === 'any' || trimmed === 'object' || trimmed === 'unknown' ) {
365+ return true
366+ }
367+
368+ // Record types like Record<string, string>, Record<string, any>, etc.
369+ if ( trimmed . startsWith ( 'Record<' ) && trimmed . endsWith ( '>' ) ) {
370+ return true
371+ }
372+
373+ // Array types like Array<any>, Array<string>, etc. (but not specific tuples)
374+ if ( trimmed . startsWith ( 'Array<' ) && trimmed . endsWith ( '>' ) ) {
375+ return true
376+ }
377+
378+ // Object types like { [key: string]: any }
379+ if ( trimmed . match ( / ^ \{ \s * \[ .* \] : \s * ( a n y | s t r i n g | n u m b e r | u n k n o w n ) \s * \} $ / ) ) {
380+ return true
381+ }
382+
383+ return false
384+ }
385+
357386/**
358387 * Process variable declaration to DTS format
359388 */
@@ -1135,7 +1164,7 @@ function parseObjectProperties(content: string): Array<[string, string]> {
11351164 inKey = false
11361165 depth = 1 // We're now inside the method definition
11371166 } else if ( char === ',' && depth === 0 ) {
1138- if ( currentKey && current . trim ( ) ) {
1167+ if ( currentKey && current . trim ( ) ) {
11391168 // Clean method signatures before storing
11401169 let value = current . trim ( )
11411170
@@ -1236,6 +1265,51 @@ function findMatchingBracket(str: string, start: number, openChar: string, close
12361265 return - 1
12371266}
12381267
1268+ /**
1269+ * Find the main arrow (=>) in a function, ignoring nested arrows in parameter types
1270+ */
1271+ function findMainArrowIndex ( str : string ) : number {
1272+ let parenDepth = 0
1273+ let bracketDepth = 0
1274+ let inString = false
1275+ let stringChar = ''
1276+
1277+ for ( let i = 0 ; i < str . length - 1 ; i ++ ) {
1278+ const char = str [ i ]
1279+ const nextChar = str [ i + 1 ]
1280+ const prevChar = i > 0 ? str [ i - 1 ] : ''
1281+
1282+ // Handle string literals
1283+ if ( ! inString && ( char === '"' || char === "'" || char === '`' ) ) {
1284+ inString = true
1285+ stringChar = char
1286+ } else if ( inString && char === stringChar && prevChar !== '\\' ) {
1287+ inString = false
1288+ }
1289+
1290+ if ( ! inString ) {
1291+ // Track nesting depth - only parentheses and square brackets
1292+ // Don't track < > as they can be comparison operators or part of generics
1293+ if ( char === '(' ) {
1294+ parenDepth ++
1295+ } else if ( char === ')' ) {
1296+ parenDepth --
1297+ } else if ( char === '[' ) {
1298+ bracketDepth ++
1299+ } else if ( char === ']' ) {
1300+ bracketDepth --
1301+ }
1302+
1303+ // Look for arrow at depth 0 (not nested inside parentheses or brackets)
1304+ if ( char === '=' && nextChar === '>' && parenDepth === 0 && bracketDepth === 0 ) {
1305+ return i
1306+ }
1307+ }
1308+ }
1309+
1310+ return - 1
1311+ }
1312+
12391313/**
12401314 * Infer function type from function expression
12411315 */
@@ -1297,7 +1371,8 @@ function inferFunctionType(value: string, inUnion: boolean = false): string {
12971371 }
12981372 }
12991373
1300- const arrowIndex = remaining . indexOf ( '=>' )
1374+ // Find the main arrow (not nested ones inside parameter types)
1375+ const arrowIndex = findMainArrowIndex ( remaining )
13011376 if ( arrowIndex === - 1 ) {
13021377 // Fallback if no arrow found
13031378 const funcType = '() => unknown'
@@ -1337,9 +1412,20 @@ function inferFunctionType(value: string, inUnion: boolean = false): string {
13371412 returnType = 'unknown'
13381413 } else if ( body . includes ( '=>' ) ) {
13391414 // This is a higher-order function returning another function
1340- // Try to infer the return function type
1341- const innerFuncType = inferFunctionType ( body , false )
1342- returnType = innerFuncType
1415+ // For complex nested functions, try to extract just the outer function signature
1416+ const outerFuncMatch = body . match ( / ^ \s * \( ( [ ^ ) ] * ) \) \s * = > / ) ;
1417+ if ( outerFuncMatch ) {
1418+ const outerParams = outerFuncMatch [ 1 ] . trim ( ) ;
1419+ // For functions like pipe that transform T => T, infer the return type from generics
1420+ if ( generics . includes ( 'T' ) && outerParams . includes ( 'T' ) ) {
1421+ returnType = `(${ outerParams } ) => T` ;
1422+ } else {
1423+ returnType = `(${ outerParams } ) => any` ;
1424+ }
1425+ } else {
1426+ // Fallback for complex cases
1427+ returnType = 'any' ;
1428+ }
13431429 } else {
13441430 // Expression body - try to infer, but be conservative in union contexts
13451431 if ( inUnion ) {
0 commit comments