code: function getUnionType(types, subtypeReduction, aliasSymbol, aliasTypeArguments) {
              if (types.length === 0) {
                  return neverType;
              }
              if (types.length === 1) {
                  return types[0];
              }
              var typeSet = [];
              addTypesToUnion(typeSet, types);
              if (typeSet.containsAny) {
                  return anyType;
              }
              if (subtypeReduction) {
                  removeSubtypes(typeSet);
              }
              if (typeSet.length === 0) {
                  return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType :
                      typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType :
                          neverType;
              }
              return getUnionTypeFromSortedList(typeSet, aliasSymbol, aliasTypeArguments);
          }
docs: We sort and deduplicate the constituent types based on object identity. If the subtypeReduction flag is specified we also reduce the constituent type set to only include types that aren't subtypes of other types. Subtype reduction is expensive for large union types and is possible only when union types are known not to circularly reference themselves (as is the case with union types created by expression constructs such as array literals and the || and ?: operators). Named types can circularly reference themselves and therefore cannot be subtype reduced during their declaration. For example, "type Item = string | (() => Item" is a named type that circularly references itself.