"Error occurs as a result of an unspecified attribute in the map

Hello, I am currently traversing a tree structure recursively. To handle undefined nodes in the tree, I have implemented guards to prevent any failures. However, during the mapping of children nodes, I encountered the following error:

Error Output

Adrian has children: Marian, Dan,
Dan is a 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 Snippet

 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 a 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;
}

Data Model

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

Note I have tried various guard combinations for handling children being null, undefined, or having a length of zero but the issue still persists on the second level when processing the 'Marian' node's children.

Input Data

let a: TreeModel = {
       id: "Adrian",
       children: [
         {id: "Dan", children: []},
         {id: "Marian", children: [ // Error occurs here while mapping children...
           {id: "Farcas", children: []},
           {id: "Liviu", children: []}
         ]}
       ]
     };

Function Call logRecursive(a);

Answer №1

The issue arises when the function this.logRecursive is called with an undefined value for this during a recursive call. This occurs because in Javascript (and Typescript), the value of this is determined by the caller, not the function declaration itself. Therefore, the caller can define any value for this when invoking a member function.

When passing this.logRecursive to the map function, it is up to map to decide what value of

this</code should be used to call <code>logRecursive
. If map does not supply a specific this, an error will occur.

To resolve this issue, one solution is to bind the value of this using this.logRecursive.bind(this) when passing the function to map. However, this approach is not recommended in Typescript due to weak typing in the current version; improvements are expected in future releases.

Another alternative is to use an arrow function, which captures the value of this from the context of its declaration.

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;
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Invalid for the purpose of storage

Encountering the following error message: The dollar ($) prefixed field '$size' in 'analytics.visits.amounts..$size' is not valid for storage. return Manager.updateMany({}, { $push: { & ...

Could it be possible for TypeScript inference to directly infer the value and omit the key in the process?

class A { state: B } class B { something: C } class C { a: string; b: boolean; } type MagicType = ... const c: MagicType<A> c.state.a = "123" c.state.b = true; Is it possible to achieve the mentioned functionality without altering the exi ...

Experience the dynamic synergy of React and typescript combined, harnessing

I am currently utilizing ReactJS with TypeScript. I have been attempting to incorporate a CDN script inside one of my components. Both index.html and .tsx component // .tsx file const handleScript = () => { // There seems to be an issue as the pr ...

Securing redirection in WebPart using Azure AD: Best practices

I've successfully created a Sharepoint Webpart with a straightforward goal: authenticate users on an external website embedded within Sharepoint. This external site utilizes Azure AD for user logins. However, my current implementation has a significa ...

Proper method for determining return type through the use of `infer`

I need to find out the return type based on input values, like in the code below: type ReturnType<S> = { array: S extends 'number' ? number[] : S extends 'string' ? string[] : never; value: S extends 'number' ? n ...

Utilizing a directive in contexts beyond a component

I have developed a popover module that consists of two components and three directives. However, I am encountering an issue where I am unable to utilize the directives outside of the main component. Whenever I try to do so, I face an editor error stating: ...

Learn how to restrict input to only specific characters in an input box using Angular2 and validations

Is it possible to restrict user input in an input box to only specific characters such as '7' and '8'? I tried adding validations with attributes like type="number", min="7" and max="8", but even then other keys can be inserted before v ...

React-router-dom TypeScript error when defining the type of the prop parameter in the loader

I'm having trouble with the params prop in the loader prop within the routes. I've defined the params in TypeScript, but I'm getting errors that I don't understand. Any help would be appreciated, thanks in advance. I tried to use the Cu ...

Having trouble resolving the signature of a class decorator when invoked as an expression with @Injectable in Angular

Error Message: Unable to resolve the signature of a class decorator when called as an expression. The argument type 'ClassDecoratorContext' is not compatible with the parameter type 'string | symbol | undefined'. After creating a book ...

What is the reason behind TypeScript choosing to define properties on the prototype rather than the object itself?

In TypeScript, I have a data object with a property defined like this: get name() { return this._hiddenName; } set name(value) { ...stuff... this._hiddenName = value; } However, when I look at the output code, I notice that the property is on ...

What is the best way to utilize the `Headers` iterator within a web browser?

Currently, I am attempting to utilize the Headers iterator as per the guidelines outlined in the Iterator documentation. let done = false while ( ! done ) { let result = headers.entries() if ( result.value ) { console.log(`yaay`) } ...

AngularFire UPDATE -> APPLY CHANGES

I can't seem to figure this out. I'm wondering how to UPDATE a document that is returned in the WHERE clause using AngularFire: constructor(private db: AngularFirestore) { } var path = this.db.collection('users').doc('type') ...

Enhancing performance with React.memo and TypeScript

I am currently developing a react native application. I am using the Item component within a flatlist to display data, however, I encountered an error in the editor regarding the second parameter of React.memo: The error message reads: 'Type 'bo ...

Pass the type of object property as an argument in the function

I've been having trouble trying to figure this out and haven't been able to find a solution in the TS docs or examples I came across. Essentially, I'm working with a configuration specifying operations on object properties and looking to en ...

The React Quill interface is unable to load due to an undefined window

I recently integrated React Quill into my Next.js project and everything was functioning properly. However, I encountered an issue when attempting to incorporate ImageResize into the editor. Upon adding the line Quill.register('modules/imageResize&ap ...

Encountered an error of 'npm ERR! invalid semver' when attempting to release an npm package

npm ERR! code EBADSEMVER npm ERR! invalid semver: npm ERR! Check out the full log of this run here: I attempted to reinstall node and semver, but unfortunately it did not resolve the issue. ...

Enhance your Vuex action types in Typescript by adding new actions or extending existing

I'm new to Typescript and I'm exploring ways to add specific type structure to all Actions declared in Vue store without repeating them in every Vuex module file. For instance, instead of manually defining types for each action in every store fi ...

Issue with displaying tab icons in Ionic 4

After updating the versions of Angular, Cordova, and Ionic, I started experiencing an issue with the tab icons displaying partially. Specifically, when my app loads with 4 tabs, only the first and third icons are visible. However, upon touching one of the ...

Sorting arrays in Typescript

Is there a way to alphabetically sort an array of objects in Typescript based on a specific field? The array I have currently looks like this - https://i.stack.imgur.com/fQ3PA.png I'm interested in sorting it alphabetically by the 'channel' ...

Error encountered while attempting to load an image in a React component using TypeScript linting

I am currently working on a React app with Next.js where I have imported an image using the following code: import image1 from '../../../img/dummy-image-2.jpg'; Subsequently, I use the image in my app like so: <img src={image1} alt="Dumm ...