Map fails due to undefined property
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
add a comment |
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
add a comment |
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
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
typescript recursion mapreduce
asked Nov 21 '18 at 16:11
Bercovici AdrianBercovici Adrian
1,0921816
1,0921816
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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;
}
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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;
}
}
add a comment |
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;
}
}
add a comment |
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;
}
}
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;
}
}
answered Nov 21 '18 at 16:19
Titian Cernicova-DragomirTitian Cernicova-Dragomir
59.5k33553
59.5k33553
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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