docs: function createType(attrs, opts) {
    if (attrs === null) {
      // Let's be helpful for this common error.
      throw new Error('invalid type: null (did you mean "null"?)');
    }
    if (Type.isType(attrs)) {
      return attrs;
    }
  
    opts = opts || {};
    opts.registry = opts.registry || {};
  
    var type;
    if (opts.typeHook && (type = opts.typeHook(attrs, opts))) {
      if (!Type.isType(type)) {
        throw new Error(f('invalid typehook return value: %j', type));
      }
      return type;
    }
  
    if (typeof attrs == 'string') { // Type reference.
      attrs = qualify(attrs, opts.namespace);
      type = opts.registry[attrs];
      if (type) {
        // Type was already defined, return it.
        return type;
      }
      if (isPrimitive(attrs)) {
        // Reference to a primitive type. These are also defined names by default
        // so we create the appropriate type and it to the registry for future
        // reference.
        return opts.registry[attrs] = createType({type: attrs}, opts);
      }
      throw new Error(f('undefined type name: %s', attrs));
    }
  
    if (attrs.logicalType && opts.logicalTypes && !LOGICAL_TYPE) {
      var DerivedType = opts.logicalTypes[attrs.logicalType];
      if (DerivedType) {
        var namespace = opts.namespace;
        var registry = {};
        Object.keys(opts.registry).forEach(function (key) {
          registry[key] = opts.registry[key];
        });
        try {
          return new DerivedType(attrs, opts);
        } catch (err) {
          if (opts.assertLogicalTypes) {
            // The spec mandates that we fall through to the underlying type if
            // the logical type is invalid. We provide this option to ease
            // debugging.
            throw err;
          }
          LOGICAL_TYPE = null;
          opts.namespace = namespace;
          opts.registry = registry;
        }
      }
    }
  
    if (Array.isArray(attrs)) { // Union.
      var UnionType = opts.wrapUnions ? WrappedUnionType : UnwrappedUnionType;
      type = new UnionType(attrs, opts);
    } else { // New type definition.
      type = (function (typeName) {
        var Type = TYPES[typeName];
        if (Type === undefined) {
          throw new Error(f('unknown type: %j', typeName));
        }
        return new Type(attrs, opts);
      })(attrs.type);
    }
    return type;
  }