@@ -421,17 +421,32 @@ export class TypeTable {
421421 return id ;
422422 }
423423
424+ // type -> [id (not unfolded), id (unfolded)]
425+ private idCache = new WeakMap < ts . Type , [ number | undefined , number | undefined ] > ( ) ;
426+
424427 /**
425428 * Gets the canonical ID for the given type, generating a fresh ID if necessary.
426429 *
427430 * Returns `null` if we do not support extraction of this type.
428431 */
429432 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+
430445 if ( this . typeRecursionDepth > 100 ) {
431446 // Ignore infinitely nested anonymous types, such as `{x: {x: {x: ... }}}`.
432447 // Such a type can't be written directly with TypeScript syntax (as it would need to be named),
433448 // but it can occur rarely as a result of type inference.
434- return null ;
449+ return setAndReturn ( null ) ;
435450 }
436451 // Replace very long string literal types with `string`.
437452 if ( ( type . flags & ts . TypeFlags . StringLiteral ) && ( ( type as ts . LiteralType ) . value as string ) . length > 30 ) {
@@ -440,12 +455,12 @@ export class TypeTable {
440455 ++ this . typeRecursionDepth ;
441456 let content = this . getTypeString ( type , unfoldAlias ) ;
442457 -- this . typeRecursionDepth ;
443- if ( content == null ) return null ; // Type not supported.
458+ if ( content == null ) return setAndReturn ( null ) ; // Type not supported.
444459 let id = this . typeIds . get ( content ) ;
445460 if ( id == null ) {
446461 let stringValue = this . stringifyType ( type , unfoldAlias ) ;
447462 if ( stringValue == null ) {
448- return null ; // Type not supported.
463+ return setAndReturn ( null ) ; // Type not supported.
449464 }
450465 id = this . typeIds . size ;
451466 this . typeIds . set ( content , id ) ;
@@ -470,7 +485,7 @@ export class TypeTable {
470485 this . buildTypeWorklist . push ( [ type , id , unfoldAlias ] ) ;
471486 }
472487 }
473- return id ;
488+ return setAndReturn ( id ) ;
474489 }
475490
476491 private stringifyType ( type : ts . Type , unfoldAlias : boolean ) : string {
0 commit comments