Skip to content

ts.TypeChecker.typeToTypeNode goes in infinite loop eating up CPU and Memory. #29564

Closed

Description

TypeScript Version: 3.2.2

Search Terms:
ts.TypeChecker.typeToTypeNode,
ts.TypeLiteralNode,
ts.NodeBuilderFlags.NoTruncation

Description:

We are trying to use typescript compiler for getting the type of ObjectLiteralExpression and for the purpose we utilize following code:

getApparentTypeForObjectLiteralExpression(node : ts.Node) : {type : ts.Type, typeNode : ts.TypeNode} {
        let type : ts.Type = this.checker.getTypeAtLocation(node);
        let typeNode = this.checker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.NoTruncation);

        if(ts.isTypeLiteralNode(typeNode))
        {
            var memberCount = typeNode.members.length;
            var name : string;
            typeNode.members.forEach(member => {
                name +=  member.name;
                name += " , ";
            });
        }
        return {type, typeNode}
    }

When we run the above code over the attached file SEA3DAmmo.txt (rename file to SEA3DAmmo.js), the line this.checker.typeToTypeNode goes into infinite loop and the application consumes high CPU and Memory and the call does not return back atall.

This is an absolute blocker, may be i am doing some mistake.
I also tried running with following options:
this.checker.typeToTypeNode(type, node, ts.NodeBuilderFlags.NoTruncation);
or
this.checker.typeToTypeNode(type, node.parent, ts.NodeBuilderFlags.NoTruncation);

Expected behavior:
It should return value and should not go in infinite loop.

SEA3DAmmo.txt

Activity

  1. abhijitparkhi1983 commented on Jan 24, 2019

    @abhijitparkhi1983
    Author

    Wesley Wigham (@weswigham) , it will be very helpful if you can guide me on this blocker issue.
    The compilation options which i am adding while creating the ts.createProgram

    var options: ts.CompilerOptions = {
                    noEmitOnError: true
                    , strict: true
                    , target: ts.ScriptTarget.Latest
                    , module: ts.ModuleKind.CommonJS
                    , skipLibCheck: true
                    , experimentalDecorators: true
                    , emitDecoratorMetadata : true
                    , allowJs: true
                    , noErrorTruncation : true
                  };
    
  2. weswigham commented on Jan 24, 2019

    @weswigham
    Member

    As a workaround, I'd try setting noErrorTruncation: false and seeing if you get some (truncated) output (and not passing ts.NodeBuilderFlags.NoTruncation).

  3. abhijitparkhi1983 commented on Jan 24, 2019

    @abhijitparkhi1983
    Author

    If i do not pass ts.NodeBuilderFlags.NoTruncation, it does work with truncated data. But I want the Non Truncated data which is equally important.

  4. weswigham commented on Jan 24, 2019

    @weswigham
    Member

    Try gradually bumping up the (ts as any).defaultMaximumTruncationLength value so you get more type-literal output so you can see what type is making us take so long to print.

  5. abhijitparkhi1983 commented on Jan 24, 2019

    @abhijitparkhi1983
    Author

    it stops at the property at line 87 from the file attached.

    getGravity: function () {
    
    		return this.gravity;
    
    	},
    
  6. weswigham commented on Jan 24, 2019

    @weswigham
    Member

    That's with the default length, yeah? With a larger truncation length (eg, 1000), where's the truncation occur (that'll be more indicative of where the problem is when truncation is off)?

  7. abhijitparkhi1983 commented on Jan 24, 2019

    @abhijitparkhi1983
    Author

    Ya thats with the default length i guess. But i am not aware how to set defaultMaximumTruncationLength.
    Where do we set it ? In compilation options?

  8. weswigham commented on Jan 24, 2019

    @weswigham
    Member

    In your code that's running this, just set (ts as any).defaultMaximumTruncationLength = 1000 (where ts is whatever you've imported typescript as) before calling the typeToString function. It's an internal member of our namespace.

  9. abhijitparkhi1983 commented on Jan 24, 2019

    @abhijitparkhi1983
    Author

    Without setting the above value and without passing ts.NodeBuilderFlags.NoTruncation , this.checker.typeToTypeNode(type) returns with 12 members where 11th member has an entry for 23 more.

    When i set (ts as any).defaultMaximumTruncationLength = 1000 before calling this.checker.typeToTypeNode(type), the number of members now shown is 19 where 18th member has 17 more.

    If i bump the value of (ts as any).defaultMaximumTruncationLength = 1000 any further, i am still getting 19 members alone

  10. weswigham commented on Jan 24, 2019

    @weswigham
    Member

    the number of members now shown is 19 where 18th member has 17 more.

    What's the actual display of this type?

  11. abhijitparkhi1983 commented on Jan 25, 2019

    @abhijitparkhi1983
    Author

    I am not sure what do u mean by display of this type?
    Its a ObjectLiteralExpression getting created, and the members are properties/functions.

    You could see the definition of this type in the file which i had attached.

  12. weswigham commented on Jan 25, 2019

    @weswigham
    Member
  13. abhijitparkhi1983 commented on Jan 25, 2019

    @abhijitparkhi1983
    Author

    Hi Wesley Wigham (@weswigham) sorry for coming late over this.
    If i understand it right, what you mean to say that the ts.createPrinter for typeNode in the above code i have shared. Right ?.

    if so, by setting (ts as any).defaultMaximumTruncationLength = 1000; and using following code

    let typeNode = this.checker.typeToTypeNode(type);
            if(printRequired)
            {
                var test = this.printer.printNode(ts.EmitHint.Unspecified, typeNode, typeNode.getSourceFile());
               
            }
    

    the value we get in test is as below:

    { world: null; rigidBodies: never[]; rigidBodiesTarget: never[]; rigidBodiesEnabled: never[]; constraints: never[]; vehicles: never[]; vehiclesWheels: never[]; ACTIVE: number; ISLAND_SLEEPING: number; WANTS_DEACTIVATION: number; DISABLE_DEACTIVATION: number; DISABLE_SIMULATION: number; VERSION: number; init: typeof init; setGravity: typeof setGravity; getGravity: () => any; setEnabledRigidBody: (rb: any, enabled: any) => { world: null; rigidBodies: never[]; rigidBodiesTarget: never[]; rigidBodiesEnabled: never[]; constraints: never[]; vehicles: never[]; vehiclesWheels: never[]; ACTIVE: number; ISLAND_SLEEPING: number; WANTS_DEACTIVATION: number; DISABLE_DEACTIVATION: number; DISABLE_SIMULATION: number; VERSION: number; init: typeof init; setGravity: typeof setGravity; getGravity: () => any; setEnabledRigidBody: ...; getEnabledRigidBody: (rb: any) => never; addRigidBody: (rb: any, target: any, enabled: any) => { world: null; rigidBodies: never[]; rigidBodiesTarget: never[]; rigidBodiesEnabled: never[]; constraints: never[]; vehicles: never[]; vehiclesWheels: never[]; ACTIVE: number; ISLAND_SLEEPING: number; WANTS_DEACTIVATION: number; DISABLE_DEACTIVATION: number; DISABLE_SIMULATION: number; VERSION: number; init: typeof init; setGravity: typeof setGravity; getGravity: () => any; setEnabledRigidBody: ...; getEnabledRigidBody: (rb: any) => never; addRigidBody: ...; removeRigidBody: (rb: any, destroy: any) => { world: null; rigidBodies: never[]; rigidBodiesTarget: never[]; rigidBodiesEnabled: never[]; constraints: never[]; vehicles: never[]; vehiclesWheels: never[]; ACTIVE: number; ISLAND_SLEEPING: number; WANTS_DEACTIVATION: number; DISABLE_DEACTIVATION: number; DISABLE_SIMULATION: number; VERSION: number; init: typeof init; setGravity: typeof setGravity; getGravity: () => any; setEnabledRigidBody: ...; getEnabledRigidBody: (rb: any) => never; addRigidBody: ...; removeRigidBody: ...; containsRigidBody: (rb: any) => boolean; addConstraint: (ctrt: any, disableCollisionsBetweenBodies: any) => { world: null; rigidBodies: never[]; rigidBodiesTarget: never[]; rigidBodiesEnabled: never[]; constraints: never[]; vehicles: never[]; vehiclesWheels: never[]; ACTIVE: number; ISLAND_SLEEPING: number; WANTS_DEACTIVATION: number; DISABLE_DEACTIVATION: number; DISABLE_SIMULATION: number; VERSION: number; init: typeof init; setGravity: typeof setGravity; getGravity: () => any; setEnabledRigidBody: ...; getEnabledRigidBody: (rb: any) => never; ... 16 more ...; update: (delta: any, iteration: any, fixedDelta: any) => { ...; }; }; ... 12 more ...; update: (delta: any, iteration: any, fixedDelta: any) => { ...; }; }; ... 14 more ...; update: (delta: any, iteration: any, fixedDelta: any) => { ...; }; }; ... 15 more ...; update: (delta: any, iteration: any, fixedDelta: any) => { ...; }; } | undefined; ... 17 more ...; update: (delta: any, iteration: any, fixedDelta: any) => { ...; }; }

    I am not sure if this is what you were looking out for.

  14. weswigham commented on Jan 25, 2019

    @weswigham
    Member

    Ya. Looks like we're printing the this return types structurally, which is not great here.

  15. abhijitparkhi1983 commented on Jan 25, 2019

    @abhijitparkhi1983
    Author

    Any ideas to go ahead with this problem ?

  16. weswigham commented on Jan 25, 2019

    @weswigham
    Member

    Hmmm, well - if you explicitly give the return type with a type annotation of some kind it'll at least short circuit the printout.

  17. weswigham commented on May 24, 2019

    @weswigham
    Member

    Nathan Shively-Sanders (@sandersn) I suspect this is identical to the issue you were looking at with js object printback and this?

  18. weswigham commented on May 28, 2019

    @weswigham
    Member

    Abhijit Ashok Parkhi (@abhijitparkhi1983) I've closed this, but if you could validate that your full example works in your local setup with our next nightly (ie, the nightly from anytime after tomorrow), that'd be swell.

  19. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions