Home > Software engineering >  Typescript error object undefined when optional
Typescript error object undefined when optional

Time:07-03

I'm not a Typescript professional but I'm getting to know a little bit and I thought I was done with the error: "Object is possibly 'undefined'.ts(2532)". But since this afternoon I have this error and I can't figure out how to indicate that my object is well defined.

I'm currently writing a parser with Chevrotain and I managed to get a tree with this parser. Now I have to use the tree to create my Predicates object.

I tried to simplify my code tell me if there is any information missing to answer me.

I have the following interface:

export interface Predicates{
    isError: boolean,
    fullPredicates: string,
    term?: Term,
    termMatcher?: TermMatcher
}

export interface Term {
    mainTerm: string,
    isNegativeTerm: boolean
}

And I have a function that fills this object by browsing a tree that contains the data I am interested in:

function extractTerm(node: CstNode): string {
    nodeTerm = node.... //get string value which contain term name
    return nodeTerm;
}

function extractFromTree(requestTree: CstNode[], fullText: string): Predicates {

    const resultPredicates: Predicates = {
        isError: false,
        fullPredicates: extractFullPredicates(requestTree, fullText) //Here this function only return a string and it work well
    };

    let currentExpression: CstNode[] = [{
        name: "",
        children: {}
    }];

    //Here I place myself on the right branch of my tree to get the data by indicating the right path in "currentExpression"
    //I removed this part to simplify but tell me if I should add it

    //If current branch exist 
    if (currentExpression[0].children[TERMINAL_LABELS.MAIN_TERM] !== undefined) {
        //Here I have the error: "Object is possibly 'undefined'.ts(2532)"
        resultPredicates.term.mainTerm = extractTerm(currentExpression[0]);
    }

    ....

    return resultPredicates as Predicates;
}

So I tried to use the two methods I know in this case to solve the error.

Attempt one:

if(resultPredicates !== undefined && resultPredicates.term !== undefined) {
    //Removes the error but at runtime the condition is considered as "undefined" and so we never enter it 
    //even though I have data and my object should be built.

    resultPredicates.term.mainTerm = extractTerm(currentExpression[0]);
}

As said in comment, this method removes the error but at runtime the condition is considered as undefined and so we never enter it while I have data and my object should be built.

Attempt two:

if (currentExpression[0].children[TERMINAL_LABELS.MAIN_TERM] !== undefined) {
    //Removes the "object is undefined" error but with this method each term of the expression has the following 
    //error: "The left-hand side of an assignment expression may not be an optional property access.ts(2779)"
    resultPredicates?.term?.mainTerm = extractTerm(currentExpression[0]);
}

As said in comment, this method removes the object is undefined error but with this method each term of the expression return the following error: The left-hand side of an assignment expression may not be an optional property access.ts(2779)

I also tried making my resultPredicates variable a Partial<Predicates> but that didn't solve my error either.

I'm stuck on this error and if someone sees what I'm doing wrong it would help me a lot. Thanks in advance if you take the time to help me.

CodePudding user response:

The compiler is helping you.

You have defined...

const resultPredicates: Predicates = {
        isError: false,
        fullPredicates: extractFullPredicates(requestTree, fullText) //Here this function only return a string and it work well
    };

and then you do

        resultPredicates.term.mainTerm = extractTerm(currentExpression[0]);

At this point, resultPredicates.term is undefined. The solution here is to define it. But this won't satisfy the compiler, because it will still be possibly undefined (assuming the type has it as optional)

You can drop off Predicates from your resultsPredicates type now, and it will understand what is and is not set. If you do not want to drop off the type then...

As you identified, you cannot use the optional chain operator, but you can instead now assert that the property exists.

        resultPredicates.term!.mainTerm = extractTerm(currentExpression[0]);

the change being the addition of ! to term.

  • Related