function isInSafeTypeofBlock(originalValueNode, node) {
  if (!node) {
    node = originalValueNode;
  }
  let parent = node.parent;
  while (parent) {
    if (!parent) {
      return false;
    }
    // Normally, if the parent block is inside a type-safe `if` statement,
    // then all child code is also type-safe. But there's a quirky case we
    // need to defend against:
    //   if (typeof obj === 'string') { } else if (typeof obj === 'object') {'' + obj}
    //   if (typeof obj === 'string') { } else {'' + obj}
    // In that code above, the `if` block is safe, but the `else` block is
    // unsafe and should report. But the AST parent of the `else` clause is the
    // `if` statement. This is the one case where the parent doesn't confer
    // safety onto the child. The code below identifies that case and keeps
    // moving up the tree until we get out of the `else`'s parent `if` block.
    // This ensures that we don't use any of these "parents" (really siblings)
    // to confer safety onto the current node.
    if (
      parent.type === 'IfStatement' &&
      !isDescendant(originalValueNode, parent.alternate)
    ) {
      const test = parent.test;
      if (isSafeTypeofExpression(originalValueNode, test)) {
        return true;
      }
    }
    parent = parent.parent;
  }
}
Returns true if the code is inside an `if` block that validates the value
  excludes symbols and objects. Examples:
if (typeof value === 'string') { }
if (typeof value === 'string' || typeof value === 'number') { }
if (typeof value === 'string' || someOtherTest) { }

  @param - originalValueNode Top-level expression to test. Kept unchanged during
  recursion.
  @param - node Expression to test at current recursion level. Will be undefined
  on non-recursive call.