target = function(var_args) {
    const klass = goog.global['ee'][name];
    const args = Array.prototype.slice.call(arguments);
    const onlyOneArg = (args.length == 1);

    // Are we trying to cast something that's already of the right class?
    if (onlyOneArg && args[0] instanceof klass) {
      return args[0];
    }

    // Constructor safety.
    if (!(this instanceof klass)) {
      return ee.ComputedObject.construct(klass, args);
    }

    // Decide whether to call a server-side constructor or just do a
    // client-side cast.
    const ctor = ee.ApiFunction.lookupInternal(name);
    const firstArgIsPrimitive = !(args[0] instanceof ee.ComputedObject);
    let shouldUseConstructor = false;
    if (ctor) {
      if (!onlyOneArg) {
        // Can't client-cast multiple arguments.
        shouldUseConstructor = true;
      } else if (firstArgIsPrimitive) {
        // Can't cast a primitive.
        shouldUseConstructor = true;
      } else if (!args[0].func ||
          args[0].func.getSignature().returns != ctor.getSignature().returns) {
        // We have a single ComputedObject argument. If it returns a different
        // type, we need to call the constructor. Otherwise this is a copy
        // constructor usage, and we can simply cast.
        shouldUseConstructor = true;
      }
    }

    // Apply our decision.
    if (shouldUseConstructor) {
      const namedArgs = ee.Types.useKeywordArgs(args, ctor.getSignature())
          ? args[0] : ctor.nameArgs(args);
      // Call manually to avoid having promote() called on the output.
      target.base(this, 'constructor', ctor, ctor.promoteArgs(namedArgs));
    } else {
      // Just cast and hope for the best.
      if (!onlyOneArg) {
        // We don't know what to do with multiple args.
        throw Error('Too many arguments for ee.' + name + '(): ' + args);
      } else if (firstArgIsPrimitive) {
        // Can't cast a primitive.
        throw Error('Invalid argument for ee.' + name + '(): ' + args +
                    '. Must be a ComputedObject.');
      }
      const theOneArg = args[0];
      target.base(this, 'constructor',
          theOneArg.func, theOneArg.args, theOneArg.varName);
    }
  }
Construct a new instance of the given class.

@param {...*} var_args The constructor args.  Can be one of:
  1) A computed value to be promoted to this type.
  2) Arguments to be passed to the algorithm with the same name as
     this class.

@return {*} The newly created class.

@constructor
@extends {ee.ComputedObject}

TODO(user): Generate docs for these classes.