SharePointBeginner
SharePointBeginner

Reputation: 359

Reduce cognitive complexity of function

I have this function that has a cognitive complexity of 24, but we only allow it to be maximum 15.

export function parameterValueParser<T extends Structure>(
  structure: T
): (parameterValue: Value) => Parsed<T> | null {
  return (parameterValue: Value): Parsed<T> | null => {
    if (isParameterValueNumber(structure)) {
      return parseNumber(parameterValue) as Parsed<T> | null;
    }
    if (isParameterValueStruct(structure)) {
      const parameterValueChildren = parseStruct(parameterValue);
      if (parameterValueChildren == null) {
        return null;
      }
      const result = {} as { [_: string]: Parsed<Structure> };
      for (const key in structure) {
        if (structure.hasOwnProperty(key)) {
          const child = parameterValueChildren[key];
          if (child == null) {
            return null;
          }
          const parsedChild = parameterValueParser(structure[key])(child);
          if (parsedChild == null) {
            return null;
          }
          result[key] = parsedChild;
        }
      }
      return result as Parsed<T>;
    }
    return null;
  };
}

One reason for the high cognitive complexity is the nestled ifs, and many under a for..of loop. So even if I would extract the code to a separate function, the cognitive complexity will be too high. How to reduce its complexity?

Upvotes: 0

Views: 487

Answers (1)

georg
georg

Reputation: 214959

This might be better suited for codereview, but I'd start refactoring by

factoring out literal types

- export function parameterValueParser<T extends Structure>(structure: T): (parameterValue: Value) => Parsed<T> | null
+ type Parser<T> = (val: Value) => Parsed<T> | null;
+ export function parameterValueParser<T extends Structure>(structure: T): Parser<T>

removing all type assertions

- return parseNumber(parameterValue) as Parsed<T> | null;
+ return parseNumber(parameterValue);

using meaningful variable names (too long names are just as bad as too short)

- const parameterValueChildren = parseStruct(parameterValue);
+ const children = parseStruct(val);

Once this is ready, you can start refactoring your logic, which will be simpler "inside-out": instead of checking the structure type in the parser, do it outside and return a specific parser for each type:

export function parameterValueParser<T extends Structure>(struct: T): Parser<T> {
    if (isParameterValueNumber(struct)) {
        return parseNumber;
    }
    if (isParameterValueStruct(struct)) {
        return structValueParser(struct);
    }
    etc....
}

Upvotes: 1

Related Questions