@@ -421,17 +421,32 @@ export class TypeTable {
421
421
return id ;
422
422
}
423
423
424
+ // type -> [id (not unfolded), id (unfolded)]
425
+ private idCache = new WeakMap < ts . Type , [ number | undefined , number | undefined ] > ( ) ;
426
+
424
427
/**
425
428
* Gets the canonical ID for the given type, generating a fresh ID if necessary.
426
429
*
427
430
* Returns `null` if we do not support extraction of this type.
428
431
*/
429
432
public getId ( type : ts . Type , unfoldAlias : boolean ) : number | null {
433
+ const cached = this . idCache . get ( type ) ;
434
+ if ( typeof cached !== "undefined" ) {
435
+ let value = cached [ unfoldAlias ? 1 : 0 ] ;
436
+ if ( typeof value !== "undefined" ) return value ;
437
+ }
438
+ const setAndReturn = ( v : number | null ) => {
439
+ let cached = this . idCache . get ( type ) || [ undefined , undefined ] ;
440
+ cached [ unfoldAlias ? 1 : 0 ] = v ;
441
+ this . idCache . set ( type , cached ) ;
442
+ return v ;
443
+ }
444
+
430
445
if ( this . typeRecursionDepth > 100 ) {
431
446
// Ignore infinitely nested anonymous types, such as `{x: {x: {x: ... }}}`.
432
447
// Such a type can't be written directly with TypeScript syntax (as it would need to be named),
433
448
// but it can occur rarely as a result of type inference.
434
- return null ;
449
+ return setAndReturn ( null ) ;
435
450
}
436
451
// Replace very long string literal types with `string`.
437
452
if ( ( type . flags & ts . TypeFlags . StringLiteral ) && ( ( type as ts . LiteralType ) . value as string ) . length > 30 ) {
@@ -440,12 +455,12 @@ export class TypeTable {
440
455
++ this . typeRecursionDepth ;
441
456
let content = this . getTypeString ( type , unfoldAlias ) ;
442
457
-- this . typeRecursionDepth ;
443
- if ( content == null ) return null ; // Type not supported.
458
+ if ( content == null ) return setAndReturn ( null ) ; // Type not supported.
444
459
let id = this . typeIds . get ( content ) ;
445
460
if ( id == null ) {
446
461
let stringValue = this . stringifyType ( type , unfoldAlias ) ;
447
462
if ( stringValue == null ) {
448
- return null ; // Type not supported.
463
+ return setAndReturn ( null ) ; // Type not supported.
449
464
}
450
465
id = this . typeIds . size ;
451
466
this . typeIds . set ( content , id ) ;
@@ -470,7 +485,7 @@ export class TypeTable {
470
485
this . buildTypeWorklist . push ( [ type , id , unfoldAlias ] ) ;
471
486
}
472
487
}
473
- return id ;
488
+ return setAndReturn ( id ) ;
474
489
}
475
490
476
491
private stringifyType ( type : ts . Type , unfoldAlias : boolean ) : string {
0 commit comments