docs: function combineObjects(types, opts) {
    var allTypes = []; // Field and value types.
    var fieldTypes = {}; // Record field types grouped by field name.
    var fieldDefaults = {};
    var isValidRecord = true;
  
    // Check whether the final type will be a map or a record.
    var i, l, type, fields;
    for (i = 0, l = types.length; i < l; i++) {
      type = types[i];
      if (type.getTypeName() === 'map') {
        isValidRecord = false;
        allTypes.push(type.getValuesType());
      } else {
        fields = type.getFields();
        var j, m, field, fieldDefault, fieldName, fieldType;
        for (j = 0, m = fields.length; j < m; j++) {
          field = fields[j];
          fieldName = field.getName();
          fieldType = field.getType();
          allTypes.push(fieldType);
          if (isValidRecord) {
            if (!fieldTypes[fieldName]) {
              fieldTypes[fieldName] = [];
            }
            fieldTypes[fieldName].push(fieldType);
            fieldDefault = field.getDefault();
            if (fieldDefault !== undefined) {
              // Later defaults will override any previous ones.
              fieldDefaults[fieldName] = fieldDefault;
            }
          }
        }
      }
    }
  
    if (isValidRecord) {
      // Check that no fields are missing and that we have the approriate
      // defaults for those which are.
      var fieldNames = Object.keys(fieldTypes);
      for (i = 0, l = fieldNames.length; i < l; i++) {
        fieldName = fieldNames[i];
        if (
          fieldTypes[fieldName].length < types.length &&
          fieldDefaults[fieldName] === undefined
        ) {
          // At least one of the records is missing a field with no default.
          if (opts && opts.strictDefaults) {
            isValidRecord = false;
          } else {
            fieldTypes[fieldName].unshift(createType('null', opts));
            fieldDefaults[fieldName] = null;
          }
        }
      }
    }
  
    var attrs;
    if (isValidRecord) {
      attrs = {
        type: 'record',
        fields: fieldNames.map(function (s) {
          var fieldType = combine(fieldTypes[s], opts);
          var fieldDefault = fieldDefaults[s];
          if (
            fieldDefault !== undefined &&
            ~fieldType.getTypeName().indexOf('union')
          ) {
            // Ensure that the default's corresponding type is first.
            var unionTypes = fieldType.getTypes();
            var i, l;
            for (i = 0, l = unionTypes.length; i < l; i++) {
              if (unionTypes[i].isValid(fieldDefault)) {
                break;
              }
            }
            if (i > 0) {
              var unionType = unionTypes[0];
              unionTypes[0] = unionTypes[i];
              unionTypes[i] = unionType;
              fieldType = createType(unionTypes, opts);
            }
          }
          return {
            name: s,
            type: fieldType,
            'default': fieldDefaults[s]
          };
        })
      };
    } else {
      attrs = {
        type: 'map',
        values: combine(allTypes, opts)
      };
    }
    return createType(attrs, opts);
  }