public static function doTypesOverlap(Schema $schema, TypeInterface $typeA, TypeInterface $typeB): bool
    {
        // Equivalent types overlap
        if ($typeA === $typeB) {
            return true;
        }

        if ($typeA instanceof AbstractTypeInterface) {
            if ($typeB instanceof AbstractTypeInterface) {
                // If both types are abstract, then determine if there is any intersection
                // between possible concrete types of each.
                return arraySome($schema->getPossibleTypes($typeA),
                    function (NamedTypeInterface $type) use ($schema, $typeB) {
                        return $schema->isPossibleType($typeB, $type);
                    });
            }

            // Determine if the latter type is a possible concrete type of the former.
            /** @noinspection PhpParamsInspection */
            return $schema->isPossibleType($typeA, $typeB);
        }

        if ($typeB instanceof AbstractTypeInterface) {
            // Determine if the former type is a possible concrete type of the latter.
            /** @noinspection PhpParamsInspection */
            return $schema->isPossibleType($typeB, $typeA);
        }

        // Otherwise the types do not overlap.
        return false;
    }