/** * 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); }
/** * Flatten Types, e.g. flatten UnionTypes. * * This function won't have much of an effect on most types, unless they contain subtypes. * * Because this function preserves duplicate entries, usually it may be preferable to use Type::unique() * which also flattens and removes duplicate entries. * * @param Type|Type[] ...$types Use array dereferencing to pass an array into this function. * * @return array */ public static function flatten(Type ...$types) { // Flatten types with subtypes e.g. UnionTypes $walker = function (Type $x) { // If the types $x contains is not just itself, go deeper! if (count($x->getTypes()) !== 1 or !first($x->getTypes())->typeof($x)) { return Type::flatten($x); } return $x->getTypes(); }; $x = array_map($walker, $types); return array_flatten($x); }