@@ -36,8 +36,11 @@ export const getValueFromType = (
3636 * Recursively generates a sample JavaScript value for a given TypeScript Type.
3737 */
3838 const generateSample = ( t : ts . Type , node : ts . Node , visited = new Set < ts . Type > ( ) ) : any => {
39- if ( visited . has ( t ) ) return null ;
40- visited . add ( t ) ;
39+ // Create a NEW visited set for each object/array to avoid blocking reuse of primitive types
40+ // We only want to prevent infinite recursion on the SAME OBJECT, not on primitive types
41+ const localVisited = new Set ( visited ) ;
42+
43+ if ( localVisited . has ( t ) ) return null ;
4144
4245 const flags = t . getFlags ( ) ;
4346
@@ -49,15 +52,15 @@ export const getValueFromType = (
4952 if ( ts . isTypeAliasDeclaration ( node ) && node . type && ts . isUnionTypeNode ( node . type ) ) {
5053 // Try to follow the order in the source code if we are at the top level
5154 const firstType = checker . getTypeFromTypeNode ( node . type . types [ 0 ] ) ;
52- return generateSample ( firstType , node , visited ) ;
55+ return generateSample ( firstType , node , localVisited ) ;
5356 }
5457
5558 const filteredTypes = t . types . filter ( subType => {
5659 const f = subType . getFlags ( ) ;
5760 return ! ( f & ts . TypeFlags . Undefined ) && ! ( f & ts . TypeFlags . Null ) ;
5861 } ) ;
5962 const typeToUse = filteredTypes . length > 0 ? filteredTypes [ 0 ] : t . types [ 0 ] ;
60- return generateSample ( typeToUse , node , visited ) ;
63+ return generateSample ( typeToUse , node , localVisited ) ;
6164 }
6265
6366 // 2. Handle Primitives and Literals
@@ -72,21 +75,24 @@ export const getValueFromType = (
7275
7376 // 3. Handle Arrays
7477 if ( checker . isArrayType ( t ) ) {
78+ localVisited . add ( t ) ;
7579 const typeRef = t as ts . TypeReference ;
7680 const elementType = typeRef . typeArguments ?. [ 0 ] || checker . getAnyType ( ) ;
77- const sample = generateSample ( elementType , node , visited ) ;
81+ const sample = generateSample ( elementType , node , localVisited ) ;
7882 return sample !== null ? [ sample ] : [ ] ;
7983 }
8084
8185 // 4. Handle Objects / Interfaces
8286 if ( t . isClassOrInterface ( ) || ( flags & ts . TypeFlags . Object ) || t . getProperties ( ) . length > 0 ) {
87+ localVisited . add ( t ) ;
8388 const obj : any = { } ;
8489 const props = t . getProperties ( ) ;
8590
8691 props . forEach ( prop => {
8792 const propType = checker . getTypeOfSymbolAtLocation ( prop , node ) ;
93+ const propDeclaration = prop . valueDeclaration ;
8894 if ( propType ) {
89- obj [ prop . getName ( ) ] = generateSample ( propType , node , visited ) ;
95+ obj [ prop . getName ( ) ] = generateSample ( propType , propDeclaration || node , localVisited ) ;
9096 }
9197 } ) ;
9298 return obj ;
0 commit comments