// Generated by scripts/generate-checked.js.

/**
 * Copyright 2016 Shape Security, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function isNotExpression(node) {
  return typeof node === 'undefined' || (node.type !== 'ArrayExpression') && (node.type !== 'ArrowExpression') && (node.type !== 'AssignmentExpression') && (node.type !== 'AwaitExpression') && (node.type !== 'BinaryExpression') && (node.type !== 'CallExpression') && (node.type !== 'ClassExpression') && (node.type !== 'CompoundAssignmentExpression') && (node.type !== 'ConditionalExpression') && (node.type !== 'FunctionExpression') && (node.type !== 'IdentifierExpression') && (node.type !== 'LiteralBooleanExpression') && (node.type !== 'LiteralInfinityExpression') && (node.type !== 'LiteralNullExpression') && (node.type !== 'LiteralNumericExpression') && (node.type !== 'LiteralRegExpExpression') && (node.type !== 'LiteralStringExpression') && ((node.type !== 'ComputedMemberExpression') && (node.type !== 'StaticMemberExpression')) && (node.type !== 'NewExpression') && (node.type !== 'NewTargetExpression') && (node.type !== 'ObjectExpression') && (node.type !== 'TemplateExpression') && (node.type !== 'ThisExpression') && (node.type !== 'UnaryExpression') && (node.type !== 'UpdateExpression') && (node.type !== 'YieldExpression') && (node.type !== 'YieldGeneratorExpression');
}

function isNotStatement(node) {
  return typeof node === 'undefined' || (node.type !== 'BlockStatement') && (node.type !== 'BreakStatement') && (node.type !== 'ClassDeclaration') && (node.type !== 'ContinueStatement') && (node.type !== 'DebuggerStatement') && (node.type !== 'EmptyStatement') && (node.type !== 'ExpressionStatement') && (node.type !== 'FunctionDeclaration') && (node.type !== 'IfStatement') && ((node.type !== 'DoWhileStatement') && (node.type !== 'ForAwaitStatement') && (node.type !== 'ForInStatement') && (node.type !== 'ForOfStatement') && (node.type !== 'ForStatement') && (node.type !== 'WhileStatement')) && (node.type !== 'LabeledStatement') && (node.type !== 'ReturnStatement') && (node.type !== 'SwitchStatement') && (node.type !== 'SwitchStatementWithDefault') && (node.type !== 'ThrowStatement') && (node.type !== 'TryCatchStatement') && (node.type !== 'TryFinallyStatement') && (node.type !== 'VariableDeclarationStatement') && (node.type !== 'WithStatement');
}

function printActualType(arg) {
  if (typeof arg !== 'object') {
    return typeof arg;
  }
  if (Array.isArray(arg)) {
    return `[${arg.map(printActualType).join(', ')}]`;
  }
  if (arg === null) {
    return null;
  }
  if (!arg.type) {
    return JSON.stringify(arg);
  }
  return arg.type;
}

function arrayEquals(a, b) {
  return a.length === b.length && a.every((v, i) => v === b[i]);
}

exports.ArrayAssignmentTarget = class {
  constructor(arg, ...extraArgs) {
    const { elements, rest } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ArrayAssignmentTarget constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements', 'rest'])) {
      throw new TypeError('Argument to ArrayAssignmentTarget constructor has wrong keys: expected {elements, rest}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || f !== null && ((f.type !== 'AssignmentTargetWithDefault') && (((f.type !== 'ArrayAssignmentTarget') && (f.type !== 'ObjectAssignmentTarget')) && ((f.type !== 'AssignmentTargetIdentifier') && ((f.type !== 'ComputedMemberAssignmentTarget') && (f.type !== 'StaticMemberAssignmentTarget'))))))) {
      throw new TypeError('Field "elements" of ArrayAssignmentTarget constructor argument is of incorrect type (expected [null or one of {AssignmentTargetWithDefault, ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}], got ' + printActualType(elements) + ')');
    }
    if (typeof rest === 'undefined' || rest !== null && (((rest.type !== 'ArrayAssignmentTarget') && (rest.type !== 'ObjectAssignmentTarget')) && ((rest.type !== 'AssignmentTargetIdentifier') && ((rest.type !== 'ComputedMemberAssignmentTarget') && (rest.type !== 'StaticMemberAssignmentTarget'))))) {
      throw new TypeError('Field "rest" of ArrayAssignmentTarget constructor argument is of incorrect type (expected null or one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(rest) + ')');
    }
    this.type = 'ArrayAssignmentTarget';
    this.elements = elements;
    this.rest = rest;
  }
};

exports.ArrayBinding = class {
  constructor(arg, ...extraArgs) {
    const { elements, rest } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ArrayBinding constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements', 'rest'])) {
      throw new TypeError('Argument to ArrayBinding constructor has wrong keys: expected {elements, rest}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || f !== null && ((f.type !== 'BindingWithDefault') && ((f.type !== 'BindingIdentifier') && ((f.type !== 'ArrayBinding') && (f.type !== 'ObjectBinding')))))) {
      throw new TypeError('Field "elements" of ArrayBinding constructor argument is of incorrect type (expected [null or one of {BindingWithDefault, BindingIdentifier, ArrayBinding, ObjectBinding}], got ' + printActualType(elements) + ')');
    }
    if (typeof rest === 'undefined' || rest !== null && ((rest.type !== 'BindingIdentifier') && ((rest.type !== 'ArrayBinding') && (rest.type !== 'ObjectBinding')))) {
      throw new TypeError('Field "rest" of ArrayBinding constructor argument is of incorrect type (expected null or one of {BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(rest) + ')');
    }
    this.type = 'ArrayBinding';
    this.elements = elements;
    this.rest = rest;
  }
};

exports.ArrayExpression = class {
  constructor(arg, ...extraArgs) {
    const { elements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ArrayExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements'])) {
      throw new TypeError('Argument to ArrayExpression constructor has wrong keys: expected {elements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || f !== null && ((isNotExpression(f)) && (f.type !== 'SpreadElement')))) {
      throw new TypeError('Field "elements" of ArrayExpression constructor argument is of incorrect type (expected [null or one of {Expression, SpreadElement}], got ' + printActualType(elements) + ')');
    }
    this.type = 'ArrayExpression';
    this.elements = elements;
  }
};

exports.ArrowExpression = class {
  constructor(arg, ...extraArgs) {
    const { isAsync, params, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ArrowExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'isAsync', 'params'])) {
      throw new TypeError('Argument to ArrowExpression constructor has wrong keys: expected {isAsync, params, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isAsync !== 'boolean') {
      throw new TypeError('Field "isAsync" of ArrowExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(isAsync) + ')');
    }
    if (typeof params === 'undefined' || params.type !== 'FormalParameters') {
      throw new TypeError('Field "params" of ArrowExpression constructor argument is of incorrect type (expected FormalParameters, got ' + printActualType(params) + ')');
    }
    if (typeof body === 'undefined' || (isNotExpression(body)) && (body.type !== 'FunctionBody')) {
      throw new TypeError('Field "body" of ArrowExpression constructor argument is of incorrect type (expected one of {Expression, FunctionBody}, got ' + printActualType(body) + ')');
    }
    this.type = 'ArrowExpression';
    this.isAsync = isAsync;
    this.params = params;
    this.body = body;
  }
};

exports.AssignmentExpression = class {
  constructor(arg, ...extraArgs) {
    const { binding, expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AssignmentExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'expression'])) {
      throw new TypeError('Argument to AssignmentExpression constructor has wrong keys: expected {binding, expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || ((binding.type !== 'ArrayAssignmentTarget') && (binding.type !== 'ObjectAssignmentTarget')) && ((binding.type !== 'AssignmentTargetIdentifier') && ((binding.type !== 'ComputedMemberAssignmentTarget') && (binding.type !== 'StaticMemberAssignmentTarget')))) {
      throw new TypeError('Field "binding" of AssignmentExpression constructor argument is of incorrect type (expected one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(binding) + ')');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of AssignmentExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'AssignmentExpression';
    this.binding = binding;
    this.expression = expression;
  }
};

exports.AssignmentTargetIdentifier = class {
  constructor(arg, ...extraArgs) {
    const { name } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AssignmentTargetIdentifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['name'])) {
      throw new TypeError('Argument to AssignmentTargetIdentifier constructor has wrong keys: expected {name}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name !== 'string') {
      throw new TypeError('Field "name" of AssignmentTargetIdentifier constructor argument is of incorrect type (expected string, got ' + printActualType(name) + ')');
    }
    this.type = 'AssignmentTargetIdentifier';
    this.name = name;
  }
};

exports.AssignmentTargetPropertyIdentifier = class {
  constructor(arg, ...extraArgs) {
    const { binding, init } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AssignmentTargetPropertyIdentifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'init'])) {
      throw new TypeError('Argument to AssignmentTargetPropertyIdentifier constructor has wrong keys: expected {binding, init}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || binding.type !== 'AssignmentTargetIdentifier') {
      throw new TypeError('Field "binding" of AssignmentTargetPropertyIdentifier constructor argument is of incorrect type (expected AssignmentTargetIdentifier, got ' + printActualType(binding) + ')');
    }
    if (typeof init === 'undefined' || init !== null && (isNotExpression(init))) {
      throw new TypeError('Field "init" of AssignmentTargetPropertyIdentifier constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(init) + ')');
    }
    this.type = 'AssignmentTargetPropertyIdentifier';
    this.binding = binding;
    this.init = init;
  }
};

exports.AssignmentTargetPropertyProperty = class {
  constructor(arg, ...extraArgs) {
    const { name, binding } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AssignmentTargetPropertyProperty constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'name'])) {
      throw new TypeError('Argument to AssignmentTargetPropertyProperty constructor has wrong keys: expected {name, binding}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of AssignmentTargetPropertyProperty constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (typeof binding === 'undefined' || (binding.type !== 'AssignmentTargetWithDefault') && (((binding.type !== 'ArrayAssignmentTarget') && (binding.type !== 'ObjectAssignmentTarget')) && ((binding.type !== 'AssignmentTargetIdentifier') && ((binding.type !== 'ComputedMemberAssignmentTarget') && (binding.type !== 'StaticMemberAssignmentTarget'))))) {
      throw new TypeError('Field "binding" of AssignmentTargetPropertyProperty constructor argument is of incorrect type (expected one of {AssignmentTargetWithDefault, ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(binding) + ')');
    }
    this.type = 'AssignmentTargetPropertyProperty';
    this.name = name;
    this.binding = binding;
  }
};

exports.AssignmentTargetWithDefault = class {
  constructor(arg, ...extraArgs) {
    const { binding, init } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AssignmentTargetWithDefault constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'init'])) {
      throw new TypeError('Argument to AssignmentTargetWithDefault constructor has wrong keys: expected {binding, init}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || ((binding.type !== 'ArrayAssignmentTarget') && (binding.type !== 'ObjectAssignmentTarget')) && ((binding.type !== 'AssignmentTargetIdentifier') && ((binding.type !== 'ComputedMemberAssignmentTarget') && (binding.type !== 'StaticMemberAssignmentTarget')))) {
      throw new TypeError('Field "binding" of AssignmentTargetWithDefault constructor argument is of incorrect type (expected one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(binding) + ')');
    }
    if (isNotExpression(init)) {
      throw new TypeError('Field "init" of AssignmentTargetWithDefault constructor argument is of incorrect type (expected Expression, got ' + printActualType(init) + ')');
    }
    this.type = 'AssignmentTargetWithDefault';
    this.binding = binding;
    this.init = init;
  }
};

exports.AwaitExpression = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('AwaitExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to AwaitExpression constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of AwaitExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'AwaitExpression';
    this.expression = expression;
  }
};

exports.BinaryExpression = class {
  constructor(arg, ...extraArgs) {
    const { left, operator, right } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BinaryExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['left', 'operator', 'right'])) {
      throw new TypeError('Argument to BinaryExpression constructor has wrong keys: expected {left, operator, right}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(left)) {
      throw new TypeError('Field "left" of BinaryExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(left) + ')');
    }
    if (typeof operator === 'undefined' || ['==', '!=', '===', '!==', '<', '<=', '>', '>=', 'in', 'instanceof', '<<', '>>', '>>>', '+', '-', '*', '/', '%', '**', ',', '||', '&&', '|', '^', '&'].indexOf(operator) === -1) {
      throw new TypeError('Field "operator" of BinaryExpression constructor argument is of incorrect type (expected one of {"==", "!=", "===", "!==", "<", "<=", ">", ">=", "in", "instanceof", "<<", ">>", ">>>", "+", "-", "*", "/", "%", "**", ",", "||", "&&", "|", "^", "&"}, got ' + printActualType(operator) + ')');
    }
    if (isNotExpression(right)) {
      throw new TypeError('Field "right" of BinaryExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(right) + ')');
    }
    this.type = 'BinaryExpression';
    this.left = left;
    this.operator = operator;
    this.right = right;
  }
};

exports.BindingIdentifier = class {
  constructor(arg, ...extraArgs) {
    const { name } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BindingIdentifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['name'])) {
      throw new TypeError('Argument to BindingIdentifier constructor has wrong keys: expected {name}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name !== 'string') {
      throw new TypeError('Field "name" of BindingIdentifier constructor argument is of incorrect type (expected string, got ' + printActualType(name) + ')');
    }
    this.type = 'BindingIdentifier';
    this.name = name;
  }
};

exports.BindingPropertyIdentifier = class {
  constructor(arg, ...extraArgs) {
    const { binding, init } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BindingPropertyIdentifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'init'])) {
      throw new TypeError('Argument to BindingPropertyIdentifier constructor has wrong keys: expected {binding, init}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || binding.type !== 'BindingIdentifier') {
      throw new TypeError('Field "binding" of BindingPropertyIdentifier constructor argument is of incorrect type (expected BindingIdentifier, got ' + printActualType(binding) + ')');
    }
    if (typeof init === 'undefined' || init !== null && (isNotExpression(init))) {
      throw new TypeError('Field "init" of BindingPropertyIdentifier constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(init) + ')');
    }
    this.type = 'BindingPropertyIdentifier';
    this.binding = binding;
    this.init = init;
  }
};

exports.BindingPropertyProperty = class {
  constructor(arg, ...extraArgs) {
    const { name, binding } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BindingPropertyProperty constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'name'])) {
      throw new TypeError('Argument to BindingPropertyProperty constructor has wrong keys: expected {name, binding}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of BindingPropertyProperty constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (typeof binding === 'undefined' || (binding.type !== 'BindingWithDefault') && ((binding.type !== 'BindingIdentifier') && ((binding.type !== 'ArrayBinding') && (binding.type !== 'ObjectBinding')))) {
      throw new TypeError('Field "binding" of BindingPropertyProperty constructor argument is of incorrect type (expected one of {BindingWithDefault, BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(binding) + ')');
    }
    this.type = 'BindingPropertyProperty';
    this.name = name;
    this.binding = binding;
  }
};

exports.BindingWithDefault = class {
  constructor(arg, ...extraArgs) {
    const { binding, init } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BindingWithDefault constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'init'])) {
      throw new TypeError('Argument to BindingWithDefault constructor has wrong keys: expected {binding, init}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || (binding.type !== 'BindingIdentifier') && ((binding.type !== 'ArrayBinding') && (binding.type !== 'ObjectBinding'))) {
      throw new TypeError('Field "binding" of BindingWithDefault constructor argument is of incorrect type (expected one of {BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(binding) + ')');
    }
    if (isNotExpression(init)) {
      throw new TypeError('Field "init" of BindingWithDefault constructor argument is of incorrect type (expected Expression, got ' + printActualType(init) + ')');
    }
    this.type = 'BindingWithDefault';
    this.binding = binding;
    this.init = init;
  }
};

exports.Block = class {
  constructor(arg, ...extraArgs) {
    const { statements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Block constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['statements'])) {
      throw new TypeError('Argument to Block constructor has wrong keys: expected {statements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(statements) || statements.some(f => isNotStatement(f))) {
      throw new TypeError('Field "statements" of Block constructor argument is of incorrect type (expected [Statement], got ' + printActualType(statements) + ')');
    }
    this.type = 'Block';
    this.statements = statements;
  }
};

exports.BlockStatement = class {
  constructor(arg, ...extraArgs) {
    const { block } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BlockStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['block'])) {
      throw new TypeError('Argument to BlockStatement constructor has wrong keys: expected {block}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof block === 'undefined' || block.type !== 'Block') {
      throw new TypeError('Field "block" of BlockStatement constructor argument is of incorrect type (expected Block, got ' + printActualType(block) + ')');
    }
    this.type = 'BlockStatement';
    this.block = block;
  }
};

exports.BreakStatement = class {
  constructor(arg, ...extraArgs) {
    const { label } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('BreakStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['label'])) {
      throw new TypeError('Argument to BreakStatement constructor has wrong keys: expected {label}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof label === 'undefined' || label !== null && (typeof label !== 'string')) {
      throw new TypeError('Field "label" of BreakStatement constructor argument is of incorrect type (expected null or string, got ' + printActualType(label) + ')');
    }
    this.type = 'BreakStatement';
    this.label = label;
  }
};

exports.CallExpression = class {
  constructor(arg, ...extraArgs) {
    const { callee, arguments: _arguments } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('CallExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['arguments', 'callee'])) {
      throw new TypeError('Argument to CallExpression constructor has wrong keys: expected {callee, arguments}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof callee === 'undefined' || (isNotExpression(callee)) && (callee.type !== 'Super')) {
      throw new TypeError('Field "callee" of CallExpression constructor argument is of incorrect type (expected one of {Expression, Super}, got ' + printActualType(callee) + ')');
    }
    if (!Array.isArray(_arguments) || _arguments.some(f => typeof f === 'undefined' || (isNotExpression(f)) && (f.type !== 'SpreadElement'))) {
      throw new TypeError('Field "arguments" of CallExpression constructor argument is of incorrect type (expected [one of {Expression, SpreadElement}], got ' + printActualType(_arguments) + ')');
    }
    this.type = 'CallExpression';
    this.callee = callee;
    this.arguments = _arguments;
  }
};

exports.CatchClause = class {
  constructor(arg, ...extraArgs) {
    const { binding, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('CatchClause constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'body'])) {
      throw new TypeError('Argument to CatchClause constructor has wrong keys: expected {binding, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || binding !== null && ((binding.type !== 'BindingIdentifier') && ((binding.type !== 'ArrayBinding') && (binding.type !== 'ObjectBinding')))) {
      throw new TypeError('Field "binding" of CatchClause constructor argument is of incorrect type (expected null or one of {BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(binding) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'Block') {
      throw new TypeError('Field "body" of CatchClause constructor argument is of incorrect type (expected Block, got ' + printActualType(body) + ')');
    }
    this.type = 'CatchClause';
    this.binding = binding;
    this.body = body;
  }
};

exports.ClassDeclaration = class {
  constructor(arg, ...extraArgs) {
    const { name, super: _super, elements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ClassDeclaration constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements', 'name', 'super'])) {
      throw new TypeError('Argument to ClassDeclaration constructor has wrong keys: expected {name, super, elements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || name.type !== 'BindingIdentifier') {
      throw new TypeError('Field "name" of ClassDeclaration constructor argument is of incorrect type (expected BindingIdentifier, got ' + printActualType(name) + ')');
    }
    if (typeof _super === 'undefined' || _super !== null && (isNotExpression(_super))) {
      throw new TypeError('Field "super" of ClassDeclaration constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(_super) + ')');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || f.type !== 'ClassElement')) {
      throw new TypeError('Field "elements" of ClassDeclaration constructor argument is of incorrect type (expected [ClassElement], got ' + printActualType(elements) + ')');
    }
    this.type = 'ClassDeclaration';
    this.name = name;
    this.super = _super;
    this.elements = elements;
  }
};

exports.ClassElement = class {
  constructor(arg, ...extraArgs) {
    const { isStatic, method } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ClassElement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['isStatic', 'method'])) {
      throw new TypeError('Argument to ClassElement constructor has wrong keys: expected {isStatic, method}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isStatic !== 'boolean') {
      throw new TypeError('Field "isStatic" of ClassElement constructor argument is of incorrect type (expected boolean, got ' + printActualType(isStatic) + ')');
    }
    if (typeof method === 'undefined' || (method.type !== 'Getter') && (method.type !== 'Method') && (method.type !== 'Setter')) {
      throw new TypeError('Field "method" of ClassElement constructor argument is of incorrect type (expected one of {Getter, Method, Setter}, got ' + printActualType(method) + ')');
    }
    this.type = 'ClassElement';
    this.isStatic = isStatic;
    this.method = method;
  }
};

exports.ClassExpression = class {
  constructor(arg, ...extraArgs) {
    const { name, super: _super, elements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ClassExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements', 'name', 'super'])) {
      throw new TypeError('Argument to ClassExpression constructor has wrong keys: expected {name, super, elements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || name !== null && (name.type !== 'BindingIdentifier')) {
      throw new TypeError('Field "name" of ClassExpression constructor argument is of incorrect type (expected null or BindingIdentifier, got ' + printActualType(name) + ')');
    }
    if (typeof _super === 'undefined' || _super !== null && (isNotExpression(_super))) {
      throw new TypeError('Field "super" of ClassExpression constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(_super) + ')');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || f.type !== 'ClassElement')) {
      throw new TypeError('Field "elements" of ClassExpression constructor argument is of incorrect type (expected [ClassElement], got ' + printActualType(elements) + ')');
    }
    this.type = 'ClassExpression';
    this.name = name;
    this.super = _super;
    this.elements = elements;
  }
};

exports.CompoundAssignmentExpression = class {
  constructor(arg, ...extraArgs) {
    const { binding, operator, expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('CompoundAssignmentExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'expression', 'operator'])) {
      throw new TypeError('Argument to CompoundAssignmentExpression constructor has wrong keys: expected {binding, operator, expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || (binding.type !== 'AssignmentTargetIdentifier') && ((binding.type !== 'ComputedMemberAssignmentTarget') && (binding.type !== 'StaticMemberAssignmentTarget'))) {
      throw new TypeError('Field "binding" of CompoundAssignmentExpression constructor argument is of incorrect type (expected one of {AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(binding) + ')');
    }
    if (typeof operator === 'undefined' || ['+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '|=', '^=', '&='].indexOf(operator) === -1) {
      throw new TypeError('Field "operator" of CompoundAssignmentExpression constructor argument is of incorrect type (expected one of {"+=", "-=", "*=", "/=", "%=", "**=", "<<=", ">>=", ">>>=", "|=", "^=", "&="}, got ' + printActualType(operator) + ')');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of CompoundAssignmentExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'CompoundAssignmentExpression';
    this.binding = binding;
    this.operator = operator;
    this.expression = expression;
  }
};

exports.ComputedMemberAssignmentTarget = class {
  constructor(arg, ...extraArgs) {
    const { object, expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ComputedMemberAssignmentTarget constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression', 'object'])) {
      throw new TypeError('Argument to ComputedMemberAssignmentTarget constructor has wrong keys: expected {object, expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof object === 'undefined' || (isNotExpression(object)) && (object.type !== 'Super')) {
      throw new TypeError('Field "object" of ComputedMemberAssignmentTarget constructor argument is of incorrect type (expected one of {Expression, Super}, got ' + printActualType(object) + ')');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of ComputedMemberAssignmentTarget constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ComputedMemberAssignmentTarget';
    this.object = object;
    this.expression = expression;
  }
};

exports.ComputedMemberExpression = class {
  constructor(arg, ...extraArgs) {
    const { object, expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ComputedMemberExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression', 'object'])) {
      throw new TypeError('Argument to ComputedMemberExpression constructor has wrong keys: expected {object, expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof object === 'undefined' || (isNotExpression(object)) && (object.type !== 'Super')) {
      throw new TypeError('Field "object" of ComputedMemberExpression constructor argument is of incorrect type (expected one of {Expression, Super}, got ' + printActualType(object) + ')');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of ComputedMemberExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ComputedMemberExpression';
    this.object = object;
    this.expression = expression;
  }
};

exports.ComputedPropertyName = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ComputedPropertyName constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to ComputedPropertyName constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of ComputedPropertyName constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ComputedPropertyName';
    this.expression = expression;
  }
};

exports.ConditionalExpression = class {
  constructor(arg, ...extraArgs) {
    const { test, consequent, alternate } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ConditionalExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['alternate', 'consequent', 'test'])) {
      throw new TypeError('Argument to ConditionalExpression constructor has wrong keys: expected {test, consequent, alternate}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(test)) {
      throw new TypeError('Field "test" of ConditionalExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(test) + ')');
    }
    if (isNotExpression(consequent)) {
      throw new TypeError('Field "consequent" of ConditionalExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(consequent) + ')');
    }
    if (isNotExpression(alternate)) {
      throw new TypeError('Field "alternate" of ConditionalExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(alternate) + ')');
    }
    this.type = 'ConditionalExpression';
    this.test = test;
    this.consequent = consequent;
    this.alternate = alternate;
  }
};

exports.ContinueStatement = class {
  constructor(arg, ...extraArgs) {
    const { label } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ContinueStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['label'])) {
      throw new TypeError('Argument to ContinueStatement constructor has wrong keys: expected {label}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof label === 'undefined' || label !== null && (typeof label !== 'string')) {
      throw new TypeError('Field "label" of ContinueStatement constructor argument is of incorrect type (expected null or string, got ' + printActualType(label) + ')');
    }
    this.type = 'ContinueStatement';
    this.label = label;
  }
};

exports.DataProperty = class {
  constructor(arg, ...extraArgs) {
    const { name, expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('DataProperty constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression', 'name'])) {
      throw new TypeError('Argument to DataProperty constructor has wrong keys: expected {name, expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of DataProperty constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of DataProperty constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'DataProperty';
    this.name = name;
    this.expression = expression;
  }
};

exports.DebuggerStatement = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('DebuggerStatement constructor takes no arguments');
    }
    this.type = 'DebuggerStatement';
  }
};

exports.Directive = class {
  constructor(arg, ...extraArgs) {
    const { rawValue } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Directive constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['rawValue'])) {
      throw new TypeError('Argument to Directive constructor has wrong keys: expected {rawValue}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof rawValue !== 'string') {
      throw new TypeError('Field "rawValue" of Directive constructor argument is of incorrect type (expected string, got ' + printActualType(rawValue) + ')');
    }
    this.type = 'Directive';
    this.rawValue = rawValue;
  }
};

exports.DoWhileStatement = class {
  constructor(arg, ...extraArgs) {
    const { body, test } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('DoWhileStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'test'])) {
      throw new TypeError('Argument to DoWhileStatement constructor has wrong keys: expected {body, test}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of DoWhileStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    if (isNotExpression(test)) {
      throw new TypeError('Field "test" of DoWhileStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(test) + ')');
    }
    this.type = 'DoWhileStatement';
    this.body = body;
    this.test = test;
  }
};

exports.EmptyStatement = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('EmptyStatement constructor takes no arguments');
    }
    this.type = 'EmptyStatement';
  }
};

exports.Export = class {
  constructor(arg, ...extraArgs) {
    const { declaration } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Export constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['declaration'])) {
      throw new TypeError('Argument to Export constructor has wrong keys: expected {declaration}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof declaration === 'undefined' || (declaration.type !== 'ClassDeclaration') && (declaration.type !== 'FunctionDeclaration') && (declaration.type !== 'VariableDeclaration')) {
      throw new TypeError('Field "declaration" of Export constructor argument is of incorrect type (expected one of {ClassDeclaration, FunctionDeclaration, VariableDeclaration}, got ' + printActualType(declaration) + ')');
    }
    this.type = 'Export';
    this.declaration = declaration;
  }
};

exports.ExportAllFrom = class {
  constructor(arg, ...extraArgs) {
    const { moduleSpecifier } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportAllFrom constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['moduleSpecifier'])) {
      throw new TypeError('Argument to ExportAllFrom constructor has wrong keys: expected {moduleSpecifier}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof moduleSpecifier !== 'string') {
      throw new TypeError('Field "moduleSpecifier" of ExportAllFrom constructor argument is of incorrect type (expected string, got ' + printActualType(moduleSpecifier) + ')');
    }
    this.type = 'ExportAllFrom';
    this.moduleSpecifier = moduleSpecifier;
  }
};

exports.ExportDefault = class {
  constructor(arg, ...extraArgs) {
    const { body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportDefault constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body'])) {
      throw new TypeError('Argument to ExportDefault constructor has wrong keys: expected {body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof body === 'undefined' || (body.type !== 'ClassDeclaration') && (isNotExpression(body)) && (body.type !== 'FunctionDeclaration')) {
      throw new TypeError('Field "body" of ExportDefault constructor argument is of incorrect type (expected one of {ClassDeclaration, Expression, FunctionDeclaration}, got ' + printActualType(body) + ')');
    }
    this.type = 'ExportDefault';
    this.body = body;
  }
};

exports.ExportFrom = class {
  constructor(arg, ...extraArgs) {
    const { namedExports, moduleSpecifier } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportFrom constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['moduleSpecifier', 'namedExports'])) {
      throw new TypeError('Argument to ExportFrom constructor has wrong keys: expected {namedExports, moduleSpecifier}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(namedExports) || namedExports.some(f => typeof f === 'undefined' || f.type !== 'ExportFromSpecifier')) {
      throw new TypeError('Field "namedExports" of ExportFrom constructor argument is of incorrect type (expected [ExportFromSpecifier], got ' + printActualType(namedExports) + ')');
    }
    if (typeof moduleSpecifier !== 'string') {
      throw new TypeError('Field "moduleSpecifier" of ExportFrom constructor argument is of incorrect type (expected string, got ' + printActualType(moduleSpecifier) + ')');
    }
    this.type = 'ExportFrom';
    this.namedExports = namedExports;
    this.moduleSpecifier = moduleSpecifier;
  }
};

exports.ExportFromSpecifier = class {
  constructor(arg, ...extraArgs) {
    const { name, exportedName } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportFromSpecifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['exportedName', 'name'])) {
      throw new TypeError('Argument to ExportFromSpecifier constructor has wrong keys: expected {name, exportedName}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name !== 'string') {
      throw new TypeError('Field "name" of ExportFromSpecifier constructor argument is of incorrect type (expected string, got ' + printActualType(name) + ')');
    }
    if (typeof exportedName === 'undefined' || exportedName !== null && (typeof exportedName !== 'string')) {
      throw new TypeError('Field "exportedName" of ExportFromSpecifier constructor argument is of incorrect type (expected null or string, got ' + printActualType(exportedName) + ')');
    }
    this.type = 'ExportFromSpecifier';
    this.name = name;
    this.exportedName = exportedName;
  }
};

exports.ExportLocalSpecifier = class {
  constructor(arg, ...extraArgs) {
    const { name, exportedName } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportLocalSpecifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['exportedName', 'name'])) {
      throw new TypeError('Argument to ExportLocalSpecifier constructor has wrong keys: expected {name, exportedName}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || name.type !== 'IdentifierExpression') {
      throw new TypeError('Field "name" of ExportLocalSpecifier constructor argument is of incorrect type (expected IdentifierExpression, got ' + printActualType(name) + ')');
    }
    if (typeof exportedName === 'undefined' || exportedName !== null && (typeof exportedName !== 'string')) {
      throw new TypeError('Field "exportedName" of ExportLocalSpecifier constructor argument is of incorrect type (expected null or string, got ' + printActualType(exportedName) + ')');
    }
    this.type = 'ExportLocalSpecifier';
    this.name = name;
    this.exportedName = exportedName;
  }
};

exports.ExportLocals = class {
  constructor(arg, ...extraArgs) {
    const { namedExports } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExportLocals constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['namedExports'])) {
      throw new TypeError('Argument to ExportLocals constructor has wrong keys: expected {namedExports}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(namedExports) || namedExports.some(f => typeof f === 'undefined' || f.type !== 'ExportLocalSpecifier')) {
      throw new TypeError('Field "namedExports" of ExportLocals constructor argument is of incorrect type (expected [ExportLocalSpecifier], got ' + printActualType(namedExports) + ')');
    }
    this.type = 'ExportLocals';
    this.namedExports = namedExports;
  }
};

exports.ExpressionStatement = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ExpressionStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to ExpressionStatement constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of ExpressionStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ExpressionStatement';
    this.expression = expression;
  }
};

exports.ForAwaitStatement = class {
  constructor(arg, ...extraArgs) {
    const { left, right, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ForAwaitStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'left', 'right'])) {
      throw new TypeError('Argument to ForAwaitStatement constructor has wrong keys: expected {left, right, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof left === 'undefined' || (((left.type !== 'ArrayAssignmentTarget') && (left.type !== 'ObjectAssignmentTarget')) && ((left.type !== 'AssignmentTargetIdentifier') && ((left.type !== 'ComputedMemberAssignmentTarget') && (left.type !== 'StaticMemberAssignmentTarget')))) && (left.type !== 'VariableDeclaration')) {
      throw new TypeError('Field "left" of ForAwaitStatement constructor argument is of incorrect type (expected one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget, VariableDeclaration}, got ' + printActualType(left) + ')');
    }
    if (isNotExpression(right)) {
      throw new TypeError('Field "right" of ForAwaitStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(right) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of ForAwaitStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'ForAwaitStatement';
    this.left = left;
    this.right = right;
    this.body = body;
  }
};

exports.ForInStatement = class {
  constructor(arg, ...extraArgs) {
    const { left, right, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ForInStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'left', 'right'])) {
      throw new TypeError('Argument to ForInStatement constructor has wrong keys: expected {left, right, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof left === 'undefined' || (((left.type !== 'ArrayAssignmentTarget') && (left.type !== 'ObjectAssignmentTarget')) && ((left.type !== 'AssignmentTargetIdentifier') && ((left.type !== 'ComputedMemberAssignmentTarget') && (left.type !== 'StaticMemberAssignmentTarget')))) && (left.type !== 'VariableDeclaration')) {
      throw new TypeError('Field "left" of ForInStatement constructor argument is of incorrect type (expected one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget, VariableDeclaration}, got ' + printActualType(left) + ')');
    }
    if (isNotExpression(right)) {
      throw new TypeError('Field "right" of ForInStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(right) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of ForInStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'ForInStatement';
    this.left = left;
    this.right = right;
    this.body = body;
  }
};

exports.ForOfStatement = class {
  constructor(arg, ...extraArgs) {
    const { left, right, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ForOfStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'left', 'right'])) {
      throw new TypeError('Argument to ForOfStatement constructor has wrong keys: expected {left, right, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof left === 'undefined' || (((left.type !== 'ArrayAssignmentTarget') && (left.type !== 'ObjectAssignmentTarget')) && ((left.type !== 'AssignmentTargetIdentifier') && ((left.type !== 'ComputedMemberAssignmentTarget') && (left.type !== 'StaticMemberAssignmentTarget')))) && (left.type !== 'VariableDeclaration')) {
      throw new TypeError('Field "left" of ForOfStatement constructor argument is of incorrect type (expected one of {ArrayAssignmentTarget, ObjectAssignmentTarget, AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget, VariableDeclaration}, got ' + printActualType(left) + ')');
    }
    if (isNotExpression(right)) {
      throw new TypeError('Field "right" of ForOfStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(right) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of ForOfStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'ForOfStatement';
    this.left = left;
    this.right = right;
    this.body = body;
  }
};

exports.ForStatement = class {
  constructor(arg, ...extraArgs) {
    const { init, test, update, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ForStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'init', 'test', 'update'])) {
      throw new TypeError('Argument to ForStatement constructor has wrong keys: expected {init, test, update, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof init === 'undefined' || init !== null && ((isNotExpression(init)) && (init.type !== 'VariableDeclaration'))) {
      throw new TypeError('Field "init" of ForStatement constructor argument is of incorrect type (expected null or one of {Expression, VariableDeclaration}, got ' + printActualType(init) + ')');
    }
    if (typeof test === 'undefined' || test !== null && (isNotExpression(test))) {
      throw new TypeError('Field "test" of ForStatement constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(test) + ')');
    }
    if (typeof update === 'undefined' || update !== null && (isNotExpression(update))) {
      throw new TypeError('Field "update" of ForStatement constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(update) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of ForStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'ForStatement';
    this.init = init;
    this.test = test;
    this.update = update;
    this.body = body;
  }
};

exports.FormalParameters = class {
  constructor(arg, ...extraArgs) {
    const { items, rest } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('FormalParameters constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['items', 'rest'])) {
      throw new TypeError('Argument to FormalParameters constructor has wrong keys: expected {items, rest}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(items) || items.some(f => typeof f === 'undefined' || (f.type !== 'BindingWithDefault') && ((f.type !== 'BindingIdentifier') && ((f.type !== 'ArrayBinding') && (f.type !== 'ObjectBinding'))))) {
      throw new TypeError('Field "items" of FormalParameters constructor argument is of incorrect type (expected [one of {BindingWithDefault, BindingIdentifier, ArrayBinding, ObjectBinding}], got ' + printActualType(items) + ')');
    }
    if (typeof rest === 'undefined' || rest !== null && ((rest.type !== 'BindingIdentifier') && ((rest.type !== 'ArrayBinding') && (rest.type !== 'ObjectBinding')))) {
      throw new TypeError('Field "rest" of FormalParameters constructor argument is of incorrect type (expected null or one of {BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(rest) + ')');
    }
    this.type = 'FormalParameters';
    this.items = items;
    this.rest = rest;
  }
};

exports.FunctionBody = class {
  constructor(arg, ...extraArgs) {
    const { directives, statements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('FunctionBody constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['directives', 'statements'])) {
      throw new TypeError('Argument to FunctionBody constructor has wrong keys: expected {directives, statements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(directives) || directives.some(f => typeof f === 'undefined' || f.type !== 'Directive')) {
      throw new TypeError('Field "directives" of FunctionBody constructor argument is of incorrect type (expected [Directive], got ' + printActualType(directives) + ')');
    }
    if (!Array.isArray(statements) || statements.some(f => isNotStatement(f))) {
      throw new TypeError('Field "statements" of FunctionBody constructor argument is of incorrect type (expected [Statement], got ' + printActualType(statements) + ')');
    }
    this.type = 'FunctionBody';
    this.directives = directives;
    this.statements = statements;
  }
};

exports.FunctionDeclaration = class {
  constructor(arg, ...extraArgs) {
    const { isAsync, isGenerator, name, params, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('FunctionDeclaration constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'isAsync', 'isGenerator', 'name', 'params'])) {
      throw new TypeError('Argument to FunctionDeclaration constructor has wrong keys: expected {isAsync, isGenerator, name, params, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isAsync !== 'boolean') {
      throw new TypeError('Field "isAsync" of FunctionDeclaration constructor argument is of incorrect type (expected boolean, got ' + printActualType(isAsync) + ')');
    }
    if (typeof isGenerator !== 'boolean') {
      throw new TypeError('Field "isGenerator" of FunctionDeclaration constructor argument is of incorrect type (expected boolean, got ' + printActualType(isGenerator) + ')');
    }
    if (typeof name === 'undefined' || name.type !== 'BindingIdentifier') {
      throw new TypeError('Field "name" of FunctionDeclaration constructor argument is of incorrect type (expected BindingIdentifier, got ' + printActualType(name) + ')');
    }
    if (typeof params === 'undefined' || params.type !== 'FormalParameters') {
      throw new TypeError('Field "params" of FunctionDeclaration constructor argument is of incorrect type (expected FormalParameters, got ' + printActualType(params) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'FunctionBody') {
      throw new TypeError('Field "body" of FunctionDeclaration constructor argument is of incorrect type (expected FunctionBody, got ' + printActualType(body) + ')');
    }
    this.type = 'FunctionDeclaration';
    this.isAsync = isAsync;
    this.isGenerator = isGenerator;
    this.name = name;
    this.params = params;
    this.body = body;
  }
};

exports.FunctionExpression = class {
  constructor(arg, ...extraArgs) {
    const { isAsync, isGenerator, name, params, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('FunctionExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'isAsync', 'isGenerator', 'name', 'params'])) {
      throw new TypeError('Argument to FunctionExpression constructor has wrong keys: expected {isAsync, isGenerator, name, params, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isAsync !== 'boolean') {
      throw new TypeError('Field "isAsync" of FunctionExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(isAsync) + ')');
    }
    if (typeof isGenerator !== 'boolean') {
      throw new TypeError('Field "isGenerator" of FunctionExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(isGenerator) + ')');
    }
    if (typeof name === 'undefined' || name !== null && (name.type !== 'BindingIdentifier')) {
      throw new TypeError('Field "name" of FunctionExpression constructor argument is of incorrect type (expected null or BindingIdentifier, got ' + printActualType(name) + ')');
    }
    if (typeof params === 'undefined' || params.type !== 'FormalParameters') {
      throw new TypeError('Field "params" of FunctionExpression constructor argument is of incorrect type (expected FormalParameters, got ' + printActualType(params) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'FunctionBody') {
      throw new TypeError('Field "body" of FunctionExpression constructor argument is of incorrect type (expected FunctionBody, got ' + printActualType(body) + ')');
    }
    this.type = 'FunctionExpression';
    this.isAsync = isAsync;
    this.isGenerator = isGenerator;
    this.name = name;
    this.params = params;
    this.body = body;
  }
};

exports.Getter = class {
  constructor(arg, ...extraArgs) {
    const { name, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Getter constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'name'])) {
      throw new TypeError('Argument to Getter constructor has wrong keys: expected {name, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of Getter constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'FunctionBody') {
      throw new TypeError('Field "body" of Getter constructor argument is of incorrect type (expected FunctionBody, got ' + printActualType(body) + ')');
    }
    this.type = 'Getter';
    this.name = name;
    this.body = body;
  }
};

exports.IdentifierExpression = class {
  constructor(arg, ...extraArgs) {
    const { name } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('IdentifierExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['name'])) {
      throw new TypeError('Argument to IdentifierExpression constructor has wrong keys: expected {name}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name !== 'string') {
      throw new TypeError('Field "name" of IdentifierExpression constructor argument is of incorrect type (expected string, got ' + printActualType(name) + ')');
    }
    this.type = 'IdentifierExpression';
    this.name = name;
  }
};

exports.IfStatement = class {
  constructor(arg, ...extraArgs) {
    const { test, consequent, alternate } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('IfStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['alternate', 'consequent', 'test'])) {
      throw new TypeError('Argument to IfStatement constructor has wrong keys: expected {test, consequent, alternate}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(test)) {
      throw new TypeError('Field "test" of IfStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(test) + ')');
    }
    if (isNotStatement(consequent)) {
      throw new TypeError('Field "consequent" of IfStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(consequent) + ')');
    }
    if (typeof alternate === 'undefined' || alternate !== null && (isNotStatement(alternate))) {
      throw new TypeError('Field "alternate" of IfStatement constructor argument is of incorrect type (expected null or Statement, got ' + printActualType(alternate) + ')');
    }
    this.type = 'IfStatement';
    this.test = test;
    this.consequent = consequent;
    this.alternate = alternate;
  }
};

exports.Import = class {
  constructor(arg, ...extraArgs) {
    const { defaultBinding, namedImports, moduleSpecifier } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Import constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['defaultBinding', 'moduleSpecifier', 'namedImports'])) {
      throw new TypeError('Argument to Import constructor has wrong keys: expected {defaultBinding, namedImports, moduleSpecifier}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof defaultBinding === 'undefined' || defaultBinding !== null && (defaultBinding.type !== 'BindingIdentifier')) {
      throw new TypeError('Field "defaultBinding" of Import constructor argument is of incorrect type (expected null or BindingIdentifier, got ' + printActualType(defaultBinding) + ')');
    }
    if (!Array.isArray(namedImports) || namedImports.some(f => typeof f === 'undefined' || f.type !== 'ImportSpecifier')) {
      throw new TypeError('Field "namedImports" of Import constructor argument is of incorrect type (expected [ImportSpecifier], got ' + printActualType(namedImports) + ')');
    }
    if (typeof moduleSpecifier !== 'string') {
      throw new TypeError('Field "moduleSpecifier" of Import constructor argument is of incorrect type (expected string, got ' + printActualType(moduleSpecifier) + ')');
    }
    this.type = 'Import';
    this.defaultBinding = defaultBinding;
    this.namedImports = namedImports;
    this.moduleSpecifier = moduleSpecifier;
  }
};

exports.ImportNamespace = class {
  constructor(arg, ...extraArgs) {
    const { defaultBinding, namespaceBinding, moduleSpecifier } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ImportNamespace constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['defaultBinding', 'moduleSpecifier', 'namespaceBinding'])) {
      throw new TypeError('Argument to ImportNamespace constructor has wrong keys: expected {defaultBinding, namespaceBinding, moduleSpecifier}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof defaultBinding === 'undefined' || defaultBinding !== null && (defaultBinding.type !== 'BindingIdentifier')) {
      throw new TypeError('Field "defaultBinding" of ImportNamespace constructor argument is of incorrect type (expected null or BindingIdentifier, got ' + printActualType(defaultBinding) + ')');
    }
    if (typeof namespaceBinding === 'undefined' || namespaceBinding.type !== 'BindingIdentifier') {
      throw new TypeError('Field "namespaceBinding" of ImportNamespace constructor argument is of incorrect type (expected BindingIdentifier, got ' + printActualType(namespaceBinding) + ')');
    }
    if (typeof moduleSpecifier !== 'string') {
      throw new TypeError('Field "moduleSpecifier" of ImportNamespace constructor argument is of incorrect type (expected string, got ' + printActualType(moduleSpecifier) + ')');
    }
    this.type = 'ImportNamespace';
    this.defaultBinding = defaultBinding;
    this.namespaceBinding = namespaceBinding;
    this.moduleSpecifier = moduleSpecifier;
  }
};

exports.ImportSpecifier = class {
  constructor(arg, ...extraArgs) {
    const { name, binding } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ImportSpecifier constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'name'])) {
      throw new TypeError('Argument to ImportSpecifier constructor has wrong keys: expected {name, binding}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || name !== null && (typeof name !== 'string')) {
      throw new TypeError('Field "name" of ImportSpecifier constructor argument is of incorrect type (expected null or string, got ' + printActualType(name) + ')');
    }
    if (typeof binding === 'undefined' || binding.type !== 'BindingIdentifier') {
      throw new TypeError('Field "binding" of ImportSpecifier constructor argument is of incorrect type (expected BindingIdentifier, got ' + printActualType(binding) + ')');
    }
    this.type = 'ImportSpecifier';
    this.name = name;
    this.binding = binding;
  }
};

exports.LabeledStatement = class {
  constructor(arg, ...extraArgs) {
    const { label, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('LabeledStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'label'])) {
      throw new TypeError('Argument to LabeledStatement constructor has wrong keys: expected {label, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof label !== 'string') {
      throw new TypeError('Field "label" of LabeledStatement constructor argument is of incorrect type (expected string, got ' + printActualType(label) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of LabeledStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'LabeledStatement';
    this.label = label;
    this.body = body;
  }
};

exports.LiteralBooleanExpression = class {
  constructor(arg, ...extraArgs) {
    const { value } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('LiteralBooleanExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['value'])) {
      throw new TypeError('Argument to LiteralBooleanExpression constructor has wrong keys: expected {value}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof value !== 'boolean') {
      throw new TypeError('Field "value" of LiteralBooleanExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(value) + ')');
    }
    this.type = 'LiteralBooleanExpression';
    this.value = value;
  }
};

exports.LiteralInfinityExpression = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('LiteralInfinityExpression constructor takes no arguments');
    }
    this.type = 'LiteralInfinityExpression';
  }
};

exports.LiteralNullExpression = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('LiteralNullExpression constructor takes no arguments');
    }
    this.type = 'LiteralNullExpression';
  }
};

exports.LiteralNumericExpression = class {
  constructor(arg, ...extraArgs) {
    const { value } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('LiteralNumericExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['value'])) {
      throw new TypeError('Argument to LiteralNumericExpression constructor has wrong keys: expected {value}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof value !== 'number') {
      throw new TypeError('Field "value" of LiteralNumericExpression constructor argument is of incorrect type (expected number, got ' + printActualType(value) + ')');
    }
    this.type = 'LiteralNumericExpression';
    this.value = value;
  }
};

exports.LiteralRegExpExpression = class {
  constructor(arg, ...extraArgs) {
    const { pattern, global, ignoreCase, multiLine, dotAll, unicode, sticky } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('LiteralRegExpExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['dotAll', 'global', 'ignoreCase', 'multiLine', 'pattern', 'sticky', 'unicode'])) {
      throw new TypeError('Argument to LiteralRegExpExpression constructor has wrong keys: expected {pattern, global, ignoreCase, multiLine, dotAll, unicode, sticky}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof pattern !== 'string') {
      throw new TypeError('Field "pattern" of LiteralRegExpExpression constructor argument is of incorrect type (expected string, got ' + printActualType(pattern) + ')');
    }
    if (typeof global !== 'boolean') {
      throw new TypeError('Field "global" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(global) + ')');
    }
    if (typeof ignoreCase !== 'boolean') {
      throw new TypeError('Field "ignoreCase" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(ignoreCase) + ')');
    }
    if (typeof multiLine !== 'boolean') {
      throw new TypeError('Field "multiLine" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(multiLine) + ')');
    }
    if (typeof dotAll !== 'boolean') {
      throw new TypeError('Field "dotAll" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(dotAll) + ')');
    }
    if (typeof unicode !== 'boolean') {
      throw new TypeError('Field "unicode" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(unicode) + ')');
    }
    if (typeof sticky !== 'boolean') {
      throw new TypeError('Field "sticky" of LiteralRegExpExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(sticky) + ')');
    }
    this.type = 'LiteralRegExpExpression';
    this.pattern = pattern;
    this.global = global;
    this.ignoreCase = ignoreCase;
    this.multiLine = multiLine;
    this.dotAll = dotAll;
    this.unicode = unicode;
    this.sticky = sticky;
  }
};

exports.LiteralStringExpression = class {
  constructor(arg, ...extraArgs) {
    const { value } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('LiteralStringExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['value'])) {
      throw new TypeError('Argument to LiteralStringExpression constructor has wrong keys: expected {value}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof value !== 'string') {
      throw new TypeError('Field "value" of LiteralStringExpression constructor argument is of incorrect type (expected string, got ' + printActualType(value) + ')');
    }
    this.type = 'LiteralStringExpression';
    this.value = value;
  }
};

exports.Method = class {
  constructor(arg, ...extraArgs) {
    const { isAsync, isGenerator, name, params, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Method constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'isAsync', 'isGenerator', 'name', 'params'])) {
      throw new TypeError('Argument to Method constructor has wrong keys: expected {isAsync, isGenerator, name, params, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isAsync !== 'boolean') {
      throw new TypeError('Field "isAsync" of Method constructor argument is of incorrect type (expected boolean, got ' + printActualType(isAsync) + ')');
    }
    if (typeof isGenerator !== 'boolean') {
      throw new TypeError('Field "isGenerator" of Method constructor argument is of incorrect type (expected boolean, got ' + printActualType(isGenerator) + ')');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of Method constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (typeof params === 'undefined' || params.type !== 'FormalParameters') {
      throw new TypeError('Field "params" of Method constructor argument is of incorrect type (expected FormalParameters, got ' + printActualType(params) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'FunctionBody') {
      throw new TypeError('Field "body" of Method constructor argument is of incorrect type (expected FunctionBody, got ' + printActualType(body) + ')');
    }
    this.type = 'Method';
    this.isAsync = isAsync;
    this.isGenerator = isGenerator;
    this.name = name;
    this.params = params;
    this.body = body;
  }
};

exports.Module = class {
  constructor(arg, ...extraArgs) {
    const { directives, items } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Module constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['directives', 'items'])) {
      throw new TypeError('Argument to Module constructor has wrong keys: expected {directives, items}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(directives) || directives.some(f => typeof f === 'undefined' || f.type !== 'Directive')) {
      throw new TypeError('Field "directives" of Module constructor argument is of incorrect type (expected [Directive], got ' + printActualType(directives) + ')');
    }
    if (!Array.isArray(items) || items.some(f => typeof f === 'undefined' || ((f.type !== 'Export') && (f.type !== 'ExportAllFrom') && (f.type !== 'ExportDefault') && (f.type !== 'ExportFrom') && (f.type !== 'ExportLocals')) && ((f.type !== 'Import') && (f.type !== 'ImportNamespace')) && (isNotStatement(f)))) {
      throw new TypeError('Field "items" of Module constructor argument is of incorrect type (expected [one of {Export, ExportAllFrom, ExportDefault, ExportFrom, ExportLocals, Import, ImportNamespace, Statement}], got ' + printActualType(items) + ')');
    }
    this.type = 'Module';
    this.directives = directives;
    this.items = items;
  }
};

exports.NewExpression = class {
  constructor(arg, ...extraArgs) {
    const { callee, arguments: _arguments } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('NewExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['arguments', 'callee'])) {
      throw new TypeError('Argument to NewExpression constructor has wrong keys: expected {callee, arguments}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(callee)) {
      throw new TypeError('Field "callee" of NewExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(callee) + ')');
    }
    if (!Array.isArray(_arguments) || _arguments.some(f => typeof f === 'undefined' || (isNotExpression(f)) && (f.type !== 'SpreadElement'))) {
      throw new TypeError('Field "arguments" of NewExpression constructor argument is of incorrect type (expected [one of {Expression, SpreadElement}], got ' + printActualType(_arguments) + ')');
    }
    this.type = 'NewExpression';
    this.callee = callee;
    this.arguments = _arguments;
  }
};

exports.NewTargetExpression = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('NewTargetExpression constructor takes no arguments');
    }
    this.type = 'NewTargetExpression';
  }
};

exports.ObjectAssignmentTarget = class {
  constructor(arg, ...extraArgs) {
    const { properties, rest } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ObjectAssignmentTarget constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['properties', 'rest'])) {
      throw new TypeError('Argument to ObjectAssignmentTarget constructor has wrong keys: expected {properties, rest}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(properties) || properties.some(f => typeof f === 'undefined' || (f.type !== 'AssignmentTargetPropertyIdentifier') && (f.type !== 'AssignmentTargetPropertyProperty'))) {
      throw new TypeError('Field "properties" of ObjectAssignmentTarget constructor argument is of incorrect type (expected [one of {AssignmentTargetPropertyIdentifier, AssignmentTargetPropertyProperty}], got ' + printActualType(properties) + ')');
    }
    if (typeof rest === 'undefined' || rest !== null && ((rest.type !== 'AssignmentTargetIdentifier') && ((rest.type !== 'ComputedMemberAssignmentTarget') && (rest.type !== 'StaticMemberAssignmentTarget')))) {
      throw new TypeError('Field "rest" of ObjectAssignmentTarget constructor argument is of incorrect type (expected null or one of {AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(rest) + ')');
    }
    this.type = 'ObjectAssignmentTarget';
    this.properties = properties;
    this.rest = rest;
  }
};

exports.ObjectBinding = class {
  constructor(arg, ...extraArgs) {
    const { properties, rest } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ObjectBinding constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['properties', 'rest'])) {
      throw new TypeError('Argument to ObjectBinding constructor has wrong keys: expected {properties, rest}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(properties) || properties.some(f => typeof f === 'undefined' || (f.type !== 'BindingPropertyIdentifier') && (f.type !== 'BindingPropertyProperty'))) {
      throw new TypeError('Field "properties" of ObjectBinding constructor argument is of incorrect type (expected [one of {BindingPropertyIdentifier, BindingPropertyProperty}], got ' + printActualType(properties) + ')');
    }
    if (typeof rest === 'undefined' || rest !== null && (rest.type !== 'BindingIdentifier')) {
      throw new TypeError('Field "rest" of ObjectBinding constructor argument is of incorrect type (expected null or BindingIdentifier, got ' + printActualType(rest) + ')');
    }
    this.type = 'ObjectBinding';
    this.properties = properties;
    this.rest = rest;
  }
};

exports.ObjectExpression = class {
  constructor(arg, ...extraArgs) {
    const { properties } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ObjectExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['properties'])) {
      throw new TypeError('Argument to ObjectExpression constructor has wrong keys: expected {properties}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(properties) || properties.some(f => typeof f === 'undefined' || ((f.type !== 'DataProperty') && ((f.type !== 'Getter') && (f.type !== 'Method') && (f.type !== 'Setter'))) && (f.type !== 'ShorthandProperty') && (f.type !== 'SpreadProperty'))) {
      throw new TypeError('Field "properties" of ObjectExpression constructor argument is of incorrect type (expected [one of {DataProperty, Getter, Method, Setter, ShorthandProperty, SpreadProperty}], got ' + printActualType(properties) + ')');
    }
    this.type = 'ObjectExpression';
    this.properties = properties;
  }
};

exports.ReturnStatement = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ReturnStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to ReturnStatement constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof expression === 'undefined' || expression !== null && (isNotExpression(expression))) {
      throw new TypeError('Field "expression" of ReturnStatement constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ReturnStatement';
    this.expression = expression;
  }
};

exports.Script = class {
  constructor(arg, ...extraArgs) {
    const { directives, statements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Script constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['directives', 'statements'])) {
      throw new TypeError('Argument to Script constructor has wrong keys: expected {directives, statements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(directives) || directives.some(f => typeof f === 'undefined' || f.type !== 'Directive')) {
      throw new TypeError('Field "directives" of Script constructor argument is of incorrect type (expected [Directive], got ' + printActualType(directives) + ')');
    }
    if (!Array.isArray(statements) || statements.some(f => isNotStatement(f))) {
      throw new TypeError('Field "statements" of Script constructor argument is of incorrect type (expected [Statement], got ' + printActualType(statements) + ')');
    }
    this.type = 'Script';
    this.directives = directives;
    this.statements = statements;
  }
};

exports.Setter = class {
  constructor(arg, ...extraArgs) {
    const { name, param, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('Setter constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'name', 'param'])) {
      throw new TypeError('Argument to Setter constructor has wrong keys: expected {name, param, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || (name.type !== 'ComputedPropertyName') && (name.type !== 'StaticPropertyName')) {
      throw new TypeError('Field "name" of Setter constructor argument is of incorrect type (expected one of {ComputedPropertyName, StaticPropertyName}, got ' + printActualType(name) + ')');
    }
    if (typeof param === 'undefined' || (param.type !== 'BindingWithDefault') && ((param.type !== 'BindingIdentifier') && ((param.type !== 'ArrayBinding') && (param.type !== 'ObjectBinding')))) {
      throw new TypeError('Field "param" of Setter constructor argument is of incorrect type (expected one of {BindingWithDefault, BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(param) + ')');
    }
    if (typeof body === 'undefined' || body.type !== 'FunctionBody') {
      throw new TypeError('Field "body" of Setter constructor argument is of incorrect type (expected FunctionBody, got ' + printActualType(body) + ')');
    }
    this.type = 'Setter';
    this.name = name;
    this.param = param;
    this.body = body;
  }
};

exports.ShorthandProperty = class {
  constructor(arg, ...extraArgs) {
    const { name } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ShorthandProperty constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['name'])) {
      throw new TypeError('Argument to ShorthandProperty constructor has wrong keys: expected {name}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof name === 'undefined' || name.type !== 'IdentifierExpression') {
      throw new TypeError('Field "name" of ShorthandProperty constructor argument is of incorrect type (expected IdentifierExpression, got ' + printActualType(name) + ')');
    }
    this.type = 'ShorthandProperty';
    this.name = name;
  }
};

exports.SpreadElement = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SpreadElement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to SpreadElement constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of SpreadElement constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'SpreadElement';
    this.expression = expression;
  }
};

exports.SpreadProperty = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SpreadProperty constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to SpreadProperty constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of SpreadProperty constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'SpreadProperty';
    this.expression = expression;
  }
};

exports.StaticMemberAssignmentTarget = class {
  constructor(arg, ...extraArgs) {
    const { object, property } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('StaticMemberAssignmentTarget constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['object', 'property'])) {
      throw new TypeError('Argument to StaticMemberAssignmentTarget constructor has wrong keys: expected {object, property}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof object === 'undefined' || (isNotExpression(object)) && (object.type !== 'Super')) {
      throw new TypeError('Field "object" of StaticMemberAssignmentTarget constructor argument is of incorrect type (expected one of {Expression, Super}, got ' + printActualType(object) + ')');
    }
    if (typeof property !== 'string') {
      throw new TypeError('Field "property" of StaticMemberAssignmentTarget constructor argument is of incorrect type (expected string, got ' + printActualType(property) + ')');
    }
    this.type = 'StaticMemberAssignmentTarget';
    this.object = object;
    this.property = property;
  }
};

exports.StaticMemberExpression = class {
  constructor(arg, ...extraArgs) {
    const { object, property } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('StaticMemberExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['object', 'property'])) {
      throw new TypeError('Argument to StaticMemberExpression constructor has wrong keys: expected {object, property}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof object === 'undefined' || (isNotExpression(object)) && (object.type !== 'Super')) {
      throw new TypeError('Field "object" of StaticMemberExpression constructor argument is of incorrect type (expected one of {Expression, Super}, got ' + printActualType(object) + ')');
    }
    if (typeof property !== 'string') {
      throw new TypeError('Field "property" of StaticMemberExpression constructor argument is of incorrect type (expected string, got ' + printActualType(property) + ')');
    }
    this.type = 'StaticMemberExpression';
    this.object = object;
    this.property = property;
  }
};

exports.StaticPropertyName = class {
  constructor(arg, ...extraArgs) {
    const { value } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('StaticPropertyName constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['value'])) {
      throw new TypeError('Argument to StaticPropertyName constructor has wrong keys: expected {value}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof value !== 'string') {
      throw new TypeError('Field "value" of StaticPropertyName constructor argument is of incorrect type (expected string, got ' + printActualType(value) + ')');
    }
    this.type = 'StaticPropertyName';
    this.value = value;
  }
};

exports.Super = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('Super constructor takes no arguments');
    }
    this.type = 'Super';
  }
};

exports.SwitchCase = class {
  constructor(arg, ...extraArgs) {
    const { test, consequent } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SwitchCase constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['consequent', 'test'])) {
      throw new TypeError('Argument to SwitchCase constructor has wrong keys: expected {test, consequent}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(test)) {
      throw new TypeError('Field "test" of SwitchCase constructor argument is of incorrect type (expected Expression, got ' + printActualType(test) + ')');
    }
    if (!Array.isArray(consequent) || consequent.some(f => isNotStatement(f))) {
      throw new TypeError('Field "consequent" of SwitchCase constructor argument is of incorrect type (expected [Statement], got ' + printActualType(consequent) + ')');
    }
    this.type = 'SwitchCase';
    this.test = test;
    this.consequent = consequent;
  }
};

exports.SwitchDefault = class {
  constructor(arg, ...extraArgs) {
    const { consequent } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SwitchDefault constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['consequent'])) {
      throw new TypeError('Argument to SwitchDefault constructor has wrong keys: expected {consequent}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (!Array.isArray(consequent) || consequent.some(f => isNotStatement(f))) {
      throw new TypeError('Field "consequent" of SwitchDefault constructor argument is of incorrect type (expected [Statement], got ' + printActualType(consequent) + ')');
    }
    this.type = 'SwitchDefault';
    this.consequent = consequent;
  }
};

exports.SwitchStatement = class {
  constructor(arg, ...extraArgs) {
    const { discriminant, cases } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SwitchStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['cases', 'discriminant'])) {
      throw new TypeError('Argument to SwitchStatement constructor has wrong keys: expected {discriminant, cases}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(discriminant)) {
      throw new TypeError('Field "discriminant" of SwitchStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(discriminant) + ')');
    }
    if (!Array.isArray(cases) || cases.some(f => typeof f === 'undefined' || f.type !== 'SwitchCase')) {
      throw new TypeError('Field "cases" of SwitchStatement constructor argument is of incorrect type (expected [SwitchCase], got ' + printActualType(cases) + ')');
    }
    this.type = 'SwitchStatement';
    this.discriminant = discriminant;
    this.cases = cases;
  }
};

exports.SwitchStatementWithDefault = class {
  constructor(arg, ...extraArgs) {
    const { discriminant, preDefaultCases, defaultCase, postDefaultCases } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('SwitchStatementWithDefault constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['defaultCase', 'discriminant', 'postDefaultCases', 'preDefaultCases'])) {
      throw new TypeError('Argument to SwitchStatementWithDefault constructor has wrong keys: expected {discriminant, preDefaultCases, defaultCase, postDefaultCases}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(discriminant)) {
      throw new TypeError('Field "discriminant" of SwitchStatementWithDefault constructor argument is of incorrect type (expected Expression, got ' + printActualType(discriminant) + ')');
    }
    if (!Array.isArray(preDefaultCases) || preDefaultCases.some(f => typeof f === 'undefined' || f.type !== 'SwitchCase')) {
      throw new TypeError('Field "preDefaultCases" of SwitchStatementWithDefault constructor argument is of incorrect type (expected [SwitchCase], got ' + printActualType(preDefaultCases) + ')');
    }
    if (typeof defaultCase === 'undefined' || defaultCase.type !== 'SwitchDefault') {
      throw new TypeError('Field "defaultCase" of SwitchStatementWithDefault constructor argument is of incorrect type (expected SwitchDefault, got ' + printActualType(defaultCase) + ')');
    }
    if (!Array.isArray(postDefaultCases) || postDefaultCases.some(f => typeof f === 'undefined' || f.type !== 'SwitchCase')) {
      throw new TypeError('Field "postDefaultCases" of SwitchStatementWithDefault constructor argument is of incorrect type (expected [SwitchCase], got ' + printActualType(postDefaultCases) + ')');
    }
    this.type = 'SwitchStatementWithDefault';
    this.discriminant = discriminant;
    this.preDefaultCases = preDefaultCases;
    this.defaultCase = defaultCase;
    this.postDefaultCases = postDefaultCases;
  }
};

exports.TemplateElement = class {
  constructor(arg, ...extraArgs) {
    const { rawValue } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('TemplateElement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['rawValue'])) {
      throw new TypeError('Argument to TemplateElement constructor has wrong keys: expected {rawValue}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof rawValue !== 'string') {
      throw new TypeError('Field "rawValue" of TemplateElement constructor argument is of incorrect type (expected string, got ' + printActualType(rawValue) + ')');
    }
    this.type = 'TemplateElement';
    this.rawValue = rawValue;
  }
};

exports.TemplateExpression = class {
  constructor(arg, ...extraArgs) {
    const { tag, elements } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('TemplateExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['elements', 'tag'])) {
      throw new TypeError('Argument to TemplateExpression constructor has wrong keys: expected {tag, elements}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof tag === 'undefined' || tag !== null && (isNotExpression(tag))) {
      throw new TypeError('Field "tag" of TemplateExpression constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(tag) + ')');
    }
    if (!Array.isArray(elements) || elements.some(f => typeof f === 'undefined' || (isNotExpression(f)) && (f.type !== 'TemplateElement'))) {
      throw new TypeError('Field "elements" of TemplateExpression constructor argument is of incorrect type (expected [one of {Expression, TemplateElement}], got ' + printActualType(elements) + ')');
    }
    this.type = 'TemplateExpression';
    this.tag = tag;
    this.elements = elements;
  }
};

exports.ThisExpression = class {
  constructor(...extraArgs) {
    if (extraArgs.length > 1 || extraArgs.length === 1 && (typeof extraArgs[0] !== 'object' || extraArgs[0] === null || Object.keys(extraArgs[0]).length !== 0)) {
      throw new TypeError('ThisExpression constructor takes no arguments');
    }
    this.type = 'ThisExpression';
  }
};

exports.ThrowStatement = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('ThrowStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to ThrowStatement constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of ThrowStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'ThrowStatement';
    this.expression = expression;
  }
};

exports.TryCatchStatement = class {
  constructor(arg, ...extraArgs) {
    const { body, catchClause } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('TryCatchStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'catchClause'])) {
      throw new TypeError('Argument to TryCatchStatement constructor has wrong keys: expected {body, catchClause}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof body === 'undefined' || body.type !== 'Block') {
      throw new TypeError('Field "body" of TryCatchStatement constructor argument is of incorrect type (expected Block, got ' + printActualType(body) + ')');
    }
    if (typeof catchClause === 'undefined' || catchClause.type !== 'CatchClause') {
      throw new TypeError('Field "catchClause" of TryCatchStatement constructor argument is of incorrect type (expected CatchClause, got ' + printActualType(catchClause) + ')');
    }
    this.type = 'TryCatchStatement';
    this.body = body;
    this.catchClause = catchClause;
  }
};

exports.TryFinallyStatement = class {
  constructor(arg, ...extraArgs) {
    const { body, catchClause, finalizer } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('TryFinallyStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'catchClause', 'finalizer'])) {
      throw new TypeError('Argument to TryFinallyStatement constructor has wrong keys: expected {body, catchClause, finalizer}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof body === 'undefined' || body.type !== 'Block') {
      throw new TypeError('Field "body" of TryFinallyStatement constructor argument is of incorrect type (expected Block, got ' + printActualType(body) + ')');
    }
    if (typeof catchClause === 'undefined' || catchClause !== null && (catchClause.type !== 'CatchClause')) {
      throw new TypeError('Field "catchClause" of TryFinallyStatement constructor argument is of incorrect type (expected null or CatchClause, got ' + printActualType(catchClause) + ')');
    }
    if (typeof finalizer === 'undefined' || finalizer.type !== 'Block') {
      throw new TypeError('Field "finalizer" of TryFinallyStatement constructor argument is of incorrect type (expected Block, got ' + printActualType(finalizer) + ')');
    }
    this.type = 'TryFinallyStatement';
    this.body = body;
    this.catchClause = catchClause;
    this.finalizer = finalizer;
  }
};

exports.UnaryExpression = class {
  constructor(arg, ...extraArgs) {
    const { operator, operand } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('UnaryExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['operand', 'operator'])) {
      throw new TypeError('Argument to UnaryExpression constructor has wrong keys: expected {operator, operand}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof operator === 'undefined' || ['+', '-', '!', '~', 'typeof', 'void', 'delete'].indexOf(operator) === -1) {
      throw new TypeError('Field "operator" of UnaryExpression constructor argument is of incorrect type (expected one of {"+", "-", "!", "~", "typeof", "void", "delete"}, got ' + printActualType(operator) + ')');
    }
    if (isNotExpression(operand)) {
      throw new TypeError('Field "operand" of UnaryExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(operand) + ')');
    }
    this.type = 'UnaryExpression';
    this.operator = operator;
    this.operand = operand;
  }
};

exports.UpdateExpression = class {
  constructor(arg, ...extraArgs) {
    const { isPrefix, operator, operand } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('UpdateExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['isPrefix', 'operand', 'operator'])) {
      throw new TypeError('Argument to UpdateExpression constructor has wrong keys: expected {isPrefix, operator, operand}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof isPrefix !== 'boolean') {
      throw new TypeError('Field "isPrefix" of UpdateExpression constructor argument is of incorrect type (expected boolean, got ' + printActualType(isPrefix) + ')');
    }
    if (typeof operator === 'undefined' || ['++', '--'].indexOf(operator) === -1) {
      throw new TypeError('Field "operator" of UpdateExpression constructor argument is of incorrect type (expected one of {"++", "--"}, got ' + printActualType(operator) + ')');
    }
    if (typeof operand === 'undefined' || (operand.type !== 'AssignmentTargetIdentifier') && ((operand.type !== 'ComputedMemberAssignmentTarget') && (operand.type !== 'StaticMemberAssignmentTarget'))) {
      throw new TypeError('Field "operand" of UpdateExpression constructor argument is of incorrect type (expected one of {AssignmentTargetIdentifier, ComputedMemberAssignmentTarget, StaticMemberAssignmentTarget}, got ' + printActualType(operand) + ')');
    }
    this.type = 'UpdateExpression';
    this.isPrefix = isPrefix;
    this.operator = operator;
    this.operand = operand;
  }
};

exports.VariableDeclaration = class {
  constructor(arg, ...extraArgs) {
    const { kind, declarators } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('VariableDeclaration constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['declarators', 'kind'])) {
      throw new TypeError('Argument to VariableDeclaration constructor has wrong keys: expected {kind, declarators}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof kind === 'undefined' || ['var', 'let', 'const'].indexOf(kind) === -1) {
      throw new TypeError('Field "kind" of VariableDeclaration constructor argument is of incorrect type (expected one of {"var", "let", "const"}, got ' + printActualType(kind) + ')');
    }
    if (!Array.isArray(declarators) || declarators.some(f => typeof f === 'undefined' || f.type !== 'VariableDeclarator')) {
      throw new TypeError('Field "declarators" of VariableDeclaration constructor argument is of incorrect type (expected [VariableDeclarator], got ' + printActualType(declarators) + ')');
    }
    this.type = 'VariableDeclaration';
    this.kind = kind;
    this.declarators = declarators;
  }
};

exports.VariableDeclarationStatement = class {
  constructor(arg, ...extraArgs) {
    const { declaration } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('VariableDeclarationStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['declaration'])) {
      throw new TypeError('Argument to VariableDeclarationStatement constructor has wrong keys: expected {declaration}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof declaration === 'undefined' || declaration.type !== 'VariableDeclaration') {
      throw new TypeError('Field "declaration" of VariableDeclarationStatement constructor argument is of incorrect type (expected VariableDeclaration, got ' + printActualType(declaration) + ')');
    }
    this.type = 'VariableDeclarationStatement';
    this.declaration = declaration;
  }
};

exports.VariableDeclarator = class {
  constructor(arg, ...extraArgs) {
    const { binding, init } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('VariableDeclarator constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['binding', 'init'])) {
      throw new TypeError('Argument to VariableDeclarator constructor has wrong keys: expected {binding, init}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof binding === 'undefined' || (binding.type !== 'BindingIdentifier') && ((binding.type !== 'ArrayBinding') && (binding.type !== 'ObjectBinding'))) {
      throw new TypeError('Field "binding" of VariableDeclarator constructor argument is of incorrect type (expected one of {BindingIdentifier, ArrayBinding, ObjectBinding}, got ' + printActualType(binding) + ')');
    }
    if (typeof init === 'undefined' || init !== null && (isNotExpression(init))) {
      throw new TypeError('Field "init" of VariableDeclarator constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(init) + ')');
    }
    this.type = 'VariableDeclarator';
    this.binding = binding;
    this.init = init;
  }
};

exports.WhileStatement = class {
  constructor(arg, ...extraArgs) {
    const { test, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('WhileStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'test'])) {
      throw new TypeError('Argument to WhileStatement constructor has wrong keys: expected {test, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(test)) {
      throw new TypeError('Field "test" of WhileStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(test) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of WhileStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'WhileStatement';
    this.test = test;
    this.body = body;
  }
};

exports.WithStatement = class {
  constructor(arg, ...extraArgs) {
    const { object, body } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('WithStatement constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['body', 'object'])) {
      throw new TypeError('Argument to WithStatement constructor has wrong keys: expected {object, body}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(object)) {
      throw new TypeError('Field "object" of WithStatement constructor argument is of incorrect type (expected Expression, got ' + printActualType(object) + ')');
    }
    if (isNotStatement(body)) {
      throw new TypeError('Field "body" of WithStatement constructor argument is of incorrect type (expected Statement, got ' + printActualType(body) + ')');
    }
    this.type = 'WithStatement';
    this.object = object;
    this.body = body;
  }
};

exports.YieldExpression = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('YieldExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to YieldExpression constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (typeof expression === 'undefined' || expression !== null && (isNotExpression(expression))) {
      throw new TypeError('Field "expression" of YieldExpression constructor argument is of incorrect type (expected null or Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'YieldExpression';
    this.expression = expression;
  }
};

exports.YieldGeneratorExpression = class {
  constructor(arg, ...extraArgs) {
    const { expression } = arg;
    if (extraArgs.length !== 0) {
      throw new TypeError('YieldGeneratorExpression constructor takes exactly one argument (' + (1 + extraArgs.length) + ' given)');
    }
    if (!arrayEquals(Object.keys(arg).sort(), ['expression'])) {
      throw new TypeError('Argument to YieldGeneratorExpression constructor has wrong keys: expected {expression}, got {' + Object.keys(arg).join(', ') + '}');
    }
    if (isNotExpression(expression)) {
      throw new TypeError('Field "expression" of YieldGeneratorExpression constructor argument is of incorrect type (expected Expression, got ' + printActualType(expression) + ')');
    }
    this.type = 'YieldGeneratorExpression';
    this.expression = expression;
  }
};
