Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript error trying to check type of array element

/** Rules to apply role */
interface RoleRule {
  logic: "and" | "or";
  rules: (
    | {
        source: "group" | "attribute";
        group?: string;
        attribute?: {
          id: string;
          operator: string;
          value: string;
        };
      }
    | RoleRule
  )[];
}

/**
 * Gets string representation of a rule.
 * 
 * @param r Rule to get string representation of
 * @returns String representation of rule
 */
const getRoleRuleString = (rule: RoleRule): string => {
  const rulesStr: string[] = [];
  rule.rules.forEach((r) => {
    if (r.rules) {
      // nested rules - recursively call this function
    }
  });
  return rulesStr.join(` ${rule.logic} `);
};

So for the getRoleRuleString function, I’m looping through the rules array of a RoleRule. The idea is to recursively call the function if the element has a rules property. However, I’m getting an error trying to check r.rules.

Property 'rules' does not exist on type 'RoleRule | { source: "group" | "attribute"; group?: string | undefined; attribute?: { id: string; operator: string; value: string; } | undefined; }'.
  Property 'rules' does not exist on type '{ source: "group" | "attribute"; group?: string | undefined; attribute?: { id: string; operator: string; value: string; } | undefined; }'

I managed to come up with this solution for it, but I feel like there is a more "corect" way of doing it.

 if (rule.hasOwnProperty('logic')) {
      const nestedAccess = rule as RoleRule;
      rulesStr.push(`(${this.getFilterString(nestedAccess)})`);
    }

I’m sure this has been asked before, but I just don’t know how to properly google it, sorry about that.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

What you’re looking for is called narrowing (formerly known as a type guard):

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-in-operator-narrowing

JavaScript has an operator for determining if an object has a property with a name: the in operator. TypeScript takes this into account as a way to narrow down potential types.

For example, with the code: "value" in x. where "value" is a string literal and x is a union type. The “true” branch narrows x’s types which have either an optional or required property value, and the “false” branch narrows to types which have an optional or missing property value.

type Fish = { swim: () => void };
type Bird = { fly: () => void };

function move(animal: Fish | Bird) {
  if ("swim" in animal) {
    return animal.swim();
  }
 
  return animal.fly();
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading