Map fails due to undefined property












0















Hello i am enumerating a tree values recursively and while some nodes in the tree are undefined i have placed guards so that it doesn't fail.Even so when map-ing the children nodes i get the error:



Output with Error



Adrian has children:Marian,Dan,
Dan is leaf
Marian has children:Liviu,Farcas,
t.ngfactory.js?
[sm]:1 ERROR TypeError: Cannot read property 'logRecursive' of undefined
at push../src/app/pages/tree-view/treeview.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
at Array.map (<anonymous>)
at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.ngOnInit (tree-view.component.ts:37)
at checkAndUpdateDirectiveInline (core.js:18537)
at checkAndUpdateNodeInline (core.js:19801)
at checkAndUpdateNode (core.js:19763)
at debugCheckAndUpdateNode (core.js:20397)
at debugCheckDirectivesFn (core.js:20357)
at Object.eval [as updateDirectives] (TreeViewComponent_Host.ngfactory.js? [sm]:1)


Code



 public logRecursive(model:TreeModel):number{
if(model==null || model ==undefined){
console.log("null");
return 0;
}
if(model.children ==undefined || model.children.length==0 ){
console.log(`${model.id} is leaf`);
return 1;
}

console.log(`${model.id} has children:${model.children.reduce((x,y)=>y.id+","+x,"")}`);
var result= model.children.map(this.logRecursive).reduce((x,y)=>x+y);
return result;
}


Model



export interface TreeModel{
id:string;
children:Array<TreeModel>;
}


P.S I Have tried all the possible guard combinations for children being null , undefined or plain length==0 and still it doesn't fail at the first level.It fails on the second level (children of 'Marian')



Input



let a:TreeModel={
id:"Adrian",
children:[
{id:"Dan",children:},
{id:"Marian",children:[ //fails when mapping his children...
{id:"Farcas",children:},
{id:"Liviu",children:}
]}
]
};


Call
logRecursive(a);










share|improve this question



























    0















    Hello i am enumerating a tree values recursively and while some nodes in the tree are undefined i have placed guards so that it doesn't fail.Even so when map-ing the children nodes i get the error:



    Output with Error



    Adrian has children:Marian,Dan,
    Dan is leaf
    Marian has children:Liviu,Farcas,
    t.ngfactory.js?
    [sm]:1 ERROR TypeError: Cannot read property 'logRecursive' of undefined
    at push../src/app/pages/tree-view/treeview.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
    at Array.map (<anonymous>)
    at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
    at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.ngOnInit (tree-view.component.ts:37)
    at checkAndUpdateDirectiveInline (core.js:18537)
    at checkAndUpdateNodeInline (core.js:19801)
    at checkAndUpdateNode (core.js:19763)
    at debugCheckAndUpdateNode (core.js:20397)
    at debugCheckDirectivesFn (core.js:20357)
    at Object.eval [as updateDirectives] (TreeViewComponent_Host.ngfactory.js? [sm]:1)


    Code



     public logRecursive(model:TreeModel):number{
    if(model==null || model ==undefined){
    console.log("null");
    return 0;
    }
    if(model.children ==undefined || model.children.length==0 ){
    console.log(`${model.id} is leaf`);
    return 1;
    }

    console.log(`${model.id} has children:${model.children.reduce((x,y)=>y.id+","+x,"")}`);
    var result= model.children.map(this.logRecursive).reduce((x,y)=>x+y);
    return result;
    }


    Model



    export interface TreeModel{
    id:string;
    children:Array<TreeModel>;
    }


    P.S I Have tried all the possible guard combinations for children being null , undefined or plain length==0 and still it doesn't fail at the first level.It fails on the second level (children of 'Marian')



    Input



    let a:TreeModel={
    id:"Adrian",
    children:[
    {id:"Dan",children:},
    {id:"Marian",children:[ //fails when mapping his children...
    {id:"Farcas",children:},
    {id:"Liviu",children:}
    ]}
    ]
    };


    Call
    logRecursive(a);










    share|improve this question

























      0












      0








      0








      Hello i am enumerating a tree values recursively and while some nodes in the tree are undefined i have placed guards so that it doesn't fail.Even so when map-ing the children nodes i get the error:



      Output with Error



      Adrian has children:Marian,Dan,
      Dan is leaf
      Marian has children:Liviu,Farcas,
      t.ngfactory.js?
      [sm]:1 ERROR TypeError: Cannot read property 'logRecursive' of undefined
      at push../src/app/pages/tree-view/treeview.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
      at Array.map (<anonymous>)
      at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
      at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.ngOnInit (tree-view.component.ts:37)
      at checkAndUpdateDirectiveInline (core.js:18537)
      at checkAndUpdateNodeInline (core.js:19801)
      at checkAndUpdateNode (core.js:19763)
      at debugCheckAndUpdateNode (core.js:20397)
      at debugCheckDirectivesFn (core.js:20357)
      at Object.eval [as updateDirectives] (TreeViewComponent_Host.ngfactory.js? [sm]:1)


      Code



       public logRecursive(model:TreeModel):number{
      if(model==null || model ==undefined){
      console.log("null");
      return 0;
      }
      if(model.children ==undefined || model.children.length==0 ){
      console.log(`${model.id} is leaf`);
      return 1;
      }

      console.log(`${model.id} has children:${model.children.reduce((x,y)=>y.id+","+x,"")}`);
      var result= model.children.map(this.logRecursive).reduce((x,y)=>x+y);
      return result;
      }


      Model



      export interface TreeModel{
      id:string;
      children:Array<TreeModel>;
      }


      P.S I Have tried all the possible guard combinations for children being null , undefined or plain length==0 and still it doesn't fail at the first level.It fails on the second level (children of 'Marian')



      Input



      let a:TreeModel={
      id:"Adrian",
      children:[
      {id:"Dan",children:},
      {id:"Marian",children:[ //fails when mapping his children...
      {id:"Farcas",children:},
      {id:"Liviu",children:}
      ]}
      ]
      };


      Call
      logRecursive(a);










      share|improve this question














      Hello i am enumerating a tree values recursively and while some nodes in the tree are undefined i have placed guards so that it doesn't fail.Even so when map-ing the children nodes i get the error:



      Output with Error



      Adrian has children:Marian,Dan,
      Dan is leaf
      Marian has children:Liviu,Farcas,
      t.ngfactory.js?
      [sm]:1 ERROR TypeError: Cannot read property 'logRecursive' of undefined
      at push../src/app/pages/tree-view/treeview.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
      at Array.map (<anonymous>)
      at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
      at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.ngOnInit (tree-view.component.ts:37)
      at checkAndUpdateDirectiveInline (core.js:18537)
      at checkAndUpdateNodeInline (core.js:19801)
      at checkAndUpdateNode (core.js:19763)
      at debugCheckAndUpdateNode (core.js:20397)
      at debugCheckDirectivesFn (core.js:20357)
      at Object.eval [as updateDirectives] (TreeViewComponent_Host.ngfactory.js? [sm]:1)


      Code



       public logRecursive(model:TreeModel):number{
      if(model==null || model ==undefined){
      console.log("null");
      return 0;
      }
      if(model.children ==undefined || model.children.length==0 ){
      console.log(`${model.id} is leaf`);
      return 1;
      }

      console.log(`${model.id} has children:${model.children.reduce((x,y)=>y.id+","+x,"")}`);
      var result= model.children.map(this.logRecursive).reduce((x,y)=>x+y);
      return result;
      }


      Model



      export interface TreeModel{
      id:string;
      children:Array<TreeModel>;
      }


      P.S I Have tried all the possible guard combinations for children being null , undefined or plain length==0 and still it doesn't fail at the first level.It fails on the second level (children of 'Marian')



      Input



      let a:TreeModel={
      id:"Adrian",
      children:[
      {id:"Dan",children:},
      {id:"Marian",children:[ //fails when mapping his children...
      {id:"Farcas",children:},
      {id:"Liviu",children:}
      ]}
      ]
      };


      Call
      logRecursive(a);







      typescript recursion mapreduce






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 21 '18 at 16:11









      Bercovici AdrianBercovici Adrian

      1,0921816




      1,0921816
























          1 Answer
          1






          active

          oldest

          votes


















          1














          The problem is that this in the call this.logRecursive is undefined on the recursive call. The reason for this is that in Javascript (and by extension Typescript) this is not decided by the function declaration but rather by the caller. So the caller can call a member function with whatever this it wants.



          When you pass this.logRecursive to map, map will decide with what this to call logRecursive. map will just not pass any this to your function and thus the error.



          The problem can be fixed either by calling this.logRecursive.bind(this) when passing the function to map in order to fix who this is. I do not recommend this in Typescript, as bind is very weakly typed at present (it will soon get better in 3.2 with this PR)



          Another option is to use an arrow function, which will capture this from declaration context.



          interface TreeModel {
          id: string;
          children: Array<TreeModel>;
          }
          let a: TreeModel = {
          id: "Adrian",
          children: [
          { id: "Dan", children: },
          {
          id: "Marian", children: [ //fails when mapping his children...
          { id: "Farcas", children: },
          { id: "Liviu", children: }
          ]
          }
          ]
          };

          class Comp {
          logRecursive(model: TreeModel): number {
          if (model == null || model == undefined) {
          console.log("null");
          return 0;
          }
          if (model.children == undefined || model.children.length == 0) {
          console.log(`${model.id} is leaf`);
          return 1;
          }

          console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
          var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
          return result;
          }
          }





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416184%2fmap-fails-due-to-undefined-property%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            The problem is that this in the call this.logRecursive is undefined on the recursive call. The reason for this is that in Javascript (and by extension Typescript) this is not decided by the function declaration but rather by the caller. So the caller can call a member function with whatever this it wants.



            When you pass this.logRecursive to map, map will decide with what this to call logRecursive. map will just not pass any this to your function and thus the error.



            The problem can be fixed either by calling this.logRecursive.bind(this) when passing the function to map in order to fix who this is. I do not recommend this in Typescript, as bind is very weakly typed at present (it will soon get better in 3.2 with this PR)



            Another option is to use an arrow function, which will capture this from declaration context.



            interface TreeModel {
            id: string;
            children: Array<TreeModel>;
            }
            let a: TreeModel = {
            id: "Adrian",
            children: [
            { id: "Dan", children: },
            {
            id: "Marian", children: [ //fails when mapping his children...
            { id: "Farcas", children: },
            { id: "Liviu", children: }
            ]
            }
            ]
            };

            class Comp {
            logRecursive(model: TreeModel): number {
            if (model == null || model == undefined) {
            console.log("null");
            return 0;
            }
            if (model.children == undefined || model.children.length == 0) {
            console.log(`${model.id} is leaf`);
            return 1;
            }

            console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
            var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
            return result;
            }
            }





            share|improve this answer




























              1














              The problem is that this in the call this.logRecursive is undefined on the recursive call. The reason for this is that in Javascript (and by extension Typescript) this is not decided by the function declaration but rather by the caller. So the caller can call a member function with whatever this it wants.



              When you pass this.logRecursive to map, map will decide with what this to call logRecursive. map will just not pass any this to your function and thus the error.



              The problem can be fixed either by calling this.logRecursive.bind(this) when passing the function to map in order to fix who this is. I do not recommend this in Typescript, as bind is very weakly typed at present (it will soon get better in 3.2 with this PR)



              Another option is to use an arrow function, which will capture this from declaration context.



              interface TreeModel {
              id: string;
              children: Array<TreeModel>;
              }
              let a: TreeModel = {
              id: "Adrian",
              children: [
              { id: "Dan", children: },
              {
              id: "Marian", children: [ //fails when mapping his children...
              { id: "Farcas", children: },
              { id: "Liviu", children: }
              ]
              }
              ]
              };

              class Comp {
              logRecursive(model: TreeModel): number {
              if (model == null || model == undefined) {
              console.log("null");
              return 0;
              }
              if (model.children == undefined || model.children.length == 0) {
              console.log(`${model.id} is leaf`);
              return 1;
              }

              console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
              var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
              return result;
              }
              }





              share|improve this answer


























                1












                1








                1







                The problem is that this in the call this.logRecursive is undefined on the recursive call. The reason for this is that in Javascript (and by extension Typescript) this is not decided by the function declaration but rather by the caller. So the caller can call a member function with whatever this it wants.



                When you pass this.logRecursive to map, map will decide with what this to call logRecursive. map will just not pass any this to your function and thus the error.



                The problem can be fixed either by calling this.logRecursive.bind(this) when passing the function to map in order to fix who this is. I do not recommend this in Typescript, as bind is very weakly typed at present (it will soon get better in 3.2 with this PR)



                Another option is to use an arrow function, which will capture this from declaration context.



                interface TreeModel {
                id: string;
                children: Array<TreeModel>;
                }
                let a: TreeModel = {
                id: "Adrian",
                children: [
                { id: "Dan", children: },
                {
                id: "Marian", children: [ //fails when mapping his children...
                { id: "Farcas", children: },
                { id: "Liviu", children: }
                ]
                }
                ]
                };

                class Comp {
                logRecursive(model: TreeModel): number {
                if (model == null || model == undefined) {
                console.log("null");
                return 0;
                }
                if (model.children == undefined || model.children.length == 0) {
                console.log(`${model.id} is leaf`);
                return 1;
                }

                console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
                var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
                return result;
                }
                }





                share|improve this answer













                The problem is that this in the call this.logRecursive is undefined on the recursive call. The reason for this is that in Javascript (and by extension Typescript) this is not decided by the function declaration but rather by the caller. So the caller can call a member function with whatever this it wants.



                When you pass this.logRecursive to map, map will decide with what this to call logRecursive. map will just not pass any this to your function and thus the error.



                The problem can be fixed either by calling this.logRecursive.bind(this) when passing the function to map in order to fix who this is. I do not recommend this in Typescript, as bind is very weakly typed at present (it will soon get better in 3.2 with this PR)



                Another option is to use an arrow function, which will capture this from declaration context.



                interface TreeModel {
                id: string;
                children: Array<TreeModel>;
                }
                let a: TreeModel = {
                id: "Adrian",
                children: [
                { id: "Dan", children: },
                {
                id: "Marian", children: [ //fails when mapping his children...
                { id: "Farcas", children: },
                { id: "Liviu", children: }
                ]
                }
                ]
                };

                class Comp {
                logRecursive(model: TreeModel): number {
                if (model == null || model == undefined) {
                console.log("null");
                return 0;
                }
                if (model.children == undefined || model.children.length == 0) {
                console.log(`${model.id} is leaf`);
                return 1;
                }

                console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
                var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
                return result;
                }
                }






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 21 '18 at 16:19









                Titian Cernicova-DragomirTitian Cernicova-Dragomir

                59.5k33553




                59.5k33553






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416184%2fmap-fails-due-to-undefined-property%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Create new schema in PostgreSQL using DBeaver

                    Deepest pit of an array with Javascript: test on Codility

                    Costa Masnaga