/** * Perform an intersection operation between two Types. * * If the two types are the same, this will just return that type. * If the two types are not the same, this will return NULL. * * When performed on two UnionTypes, this operation will return another * Type or UnionType containing the types that were equal from a many-to-many * typeof() operation or NULL if there are no matches. * * UnionType->intersect(NormalType) * When performed on a UnionType and one normal Type, this operation * will return the normal type if the UnionType contains the Type, or * NULL otherwise. * * NormalType->intersect(UnionType) * When performed on a Type and one UnionType, this operation will * return the Type if the UnionType contains it. NULL otherwise. * * Strict operation. * * @param Type $a * @param Type $b * * @return Type|null */ public static final function intersect(Type $a, Type $b) { // Intersecting between $a and $b $output = []; $a = $a->getTypes(); $b = $b->getTypes(); // Check all elements of $a foreach ($a as $x) { foreach ($b as $y) { if ($x->typeof($y)) { $output[] = $x; } } } // Check all elements of $b foreach ($b as $x) { foreach ($a as $y) { if ($x->typeof($y)) { $output[] = $x; } } } // Combine results return Type::unique(...$output) ?: null; }
/** * Check if all types are the same, in which case just return that type. * Otherwise, create the UnionType and return. * Also automatically flatten all nested UnionTypes. * * @param Type $type Require at least one type * @param Type|Type[] ...$types * * @return UnionType|Type */ public static function createIfNotDuplicate(Type $type, Type ...$types) { $types = array_merge([$type], $types); // Flatten nested UnionTypes $types = Type::flatten($types); if (array_any($types, function (Type $type, $key, array $collection) { return $type instanceof UnionType; })) { throw new \LogicException("UnionType::flatten() failed to flatten nested UnionTypes."); } $types = Type::unique($types); if (count($types) <= 1) { return first($types); } return new UnionType(array_shift($types), $types); }