@@ -310,72 +310,64 @@ function transformSchemaObjectCore(schemaObject: SchemaObject, options: Transfor
310
310
311
311
// type: array (with support for tuples)
312
312
if ( schemaObject . type === "array" ) {
313
- // default to `unknown[]`
314
- let itemType : ts . TypeNode = UNKNOWN ;
315
- // tuple type
316
- if ( schemaObject . prefixItems || Array . isArray ( schemaObject . items ) ) {
317
- const prefixItems = schemaObject . prefixItems ?? ( schemaObject . items as ( SchemaObject | ReferenceObject ) [ ] ) ;
318
- itemType = ts . factory . createTupleTypeNode ( prefixItems . map ( ( item ) => transformSchemaObject ( item , options ) ) ) ;
319
- }
320
- // standard array type
321
- else if ( schemaObject . items ) {
322
- if ( hasKey ( schemaObject . items , "type" ) && schemaObject . items . type === "array" ) {
323
- itemType = ts . factory . createArrayTypeNode ( transformSchemaObject ( schemaObject . items , options ) ) ;
324
- } else {
325
- itemType = transformSchemaObject ( schemaObject . items , options ) ;
313
+ const arrayType = ( ( ) => {
314
+ // tuple type
315
+ if ( schemaObject . prefixItems || Array . isArray ( schemaObject . items ) ) {
316
+ const prefixItems = schemaObject . prefixItems ?? ( schemaObject . items as ( SchemaObject | ReferenceObject ) [ ] ) ;
317
+ return ts . factory . createTupleTypeNode ( prefixItems . map ( ( item ) => transformSchemaObject ( item , options ) ) ) ;
326
318
}
327
- }
328
319
329
- const min : number =
330
- typeof schemaObject . minItems === "number" && schemaObject . minItems >= 0 ? schemaObject . minItems : 0 ;
331
- const max : number | undefined =
332
- typeof schemaObject . maxItems === "number" && schemaObject . maxItems >= 0 && min <= schemaObject . maxItems
333
- ? schemaObject . maxItems
334
- : undefined ;
335
- const estimateCodeSize = typeof max !== "number" ? min : ( max * ( max + 1 ) - min * ( min - 1 ) ) / 2 ;
336
- if (
337
- options . ctx . arrayLength &&
338
- ( min !== 0 || max !== undefined ) &&
339
- estimateCodeSize < 30 // "30" is an arbitrary number but roughly around when TS starts to struggle with tuple inference in practice
340
- ) {
341
- if ( min === max ) {
342
- const elements : ts . TypeNode [ ] = [ ] ;
343
- for ( let i = 0 ; i < min ; i ++ ) {
344
- elements . push ( itemType ) ;
345
- }
346
- return tsUnion ( [ ts . factory . createTupleTypeNode ( elements ) ] ) ;
347
- } else if ( ( schemaObject . maxItems as number ) > 0 ) {
348
- // if maxItems is set, then return a union of all permutations of possible tuple types
349
- const members : ts . TypeNode [ ] = [ ] ;
350
- // populate 1 short of min …
351
- for ( let i = 0 ; i <= ( max ?? 0 ) - min ; i ++ ) {
320
+ // standard array type
321
+ const itemType : ts . TypeNode = schemaObject . items ? transformSchemaObject ( schemaObject . items , options ) : UNKNOWN ;
322
+
323
+ const min : number =
324
+ typeof schemaObject . minItems === "number" && schemaObject . minItems >= 0 ? schemaObject . minItems : 0 ;
325
+ const max : number | undefined =
326
+ typeof schemaObject . maxItems === "number" && schemaObject . maxItems >= 0 && min <= schemaObject . maxItems
327
+ ? schemaObject . maxItems
328
+ : undefined ;
329
+ const estimateCodeSize = typeof max !== "number" ? min : ( max * ( max + 1 ) - min * ( min - 1 ) ) / 2 ;
330
+ if (
331
+ options . ctx . arrayLength &&
332
+ ( min !== 0 || max !== undefined ) &&
333
+ estimateCodeSize < 30 // "30" is an arbitrary number but roughly around when TS starts to struggle with tuple inference in practice
334
+ ) {
335
+ if ( min === max ) {
352
336
const elements : ts . TypeNode [ ] = [ ] ;
353
- for ( let j = min ; j < i + min ; j ++ ) {
337
+ for ( let i = 0 ; i < min ; i ++ ) {
354
338
elements . push ( itemType ) ;
355
339
}
356
- members . push ( ts . factory . createTupleTypeNode ( elements ) ) ;
340
+ return tsUnion ( [ ts . factory . createTupleTypeNode ( elements ) ] ) ;
341
+ } else if ( ( schemaObject . maxItems as number ) > 0 ) {
342
+ // if maxItems is set, then return a union of all permutations of possible tuple types
343
+ const members : ts . TypeNode [ ] = [ ] ;
344
+ // populate 1 short of min …
345
+ for ( let i = 0 ; i <= ( max ?? 0 ) - min ; i ++ ) {
346
+ const elements : ts . TypeNode [ ] = [ ] ;
347
+ for ( let j = min ; j < i + min ; j ++ ) {
348
+ elements . push ( itemType ) ;
349
+ }
350
+ members . push ( ts . factory . createTupleTypeNode ( elements ) ) ;
351
+ }
352
+ return tsUnion ( members ) ;
357
353
}
358
- return tsUnion ( members ) ;
359
- }
360
- // if maxItems not set, then return a simple tuple type the length of `min`
361
- else {
362
- const elements : ts . TypeNode [ ] = [ ] ;
363
- for ( let i = 0 ; i < min ; i ++ ) {
364
- elements . push ( itemType ) ;
354
+ // if maxItems not set, then return a simple tuple type the length of `min`
355
+ else {
356
+ const elements : ts . TypeNode [ ] = [ ] ;
357
+ for ( let i = 0 ; i < min ; i ++ ) {
358
+ elements . push ( itemType ) ;
359
+ }
360
+ elements . push ( ts . factory . createRestTypeNode ( ts . factory . createArrayTypeNode ( itemType ) ) ) ;
361
+ return ts . factory . createTupleTypeNode ( elements ) ;
365
362
}
366
- elements . push ( ts . factory . createRestTypeNode ( ts . factory . createArrayTypeNode ( itemType ) ) ) ;
367
- return ts . factory . createTupleTypeNode ( elements ) ;
368
363
}
369
- }
370
364
371
- const finalType =
372
- ts . isTupleTypeNode ( itemType ) || ts . isArrayTypeNode ( itemType )
373
- ? itemType
374
- : ts . factory . createArrayTypeNode ( itemType ) ; // wrap itemType in array type, but only if not a tuple or array already
365
+ return ts . factory . createArrayTypeNode ( itemType ) ;
366
+ } ) ( ) ;
375
367
376
368
return options . ctx . immutable
377
- ? ts . factory . createTypeOperatorNode ( ts . SyntaxKind . ReadonlyKeyword , finalType )
378
- : finalType ;
369
+ ? ts . factory . createTypeOperatorNode ( ts . SyntaxKind . ReadonlyKeyword , arrayType )
370
+ : arrayType ;
379
371
}
380
372
381
373
// polymorphic, or 3.1 nullable
0 commit comments