Repository: babel/babel
File: packages/babel-types/src/definitions/utils.ts (TypeScript)

Code before:
export function arrayOfType(...typeNames: NodeTypes[]) {
  return arrayOf(assertNodeType(...typeNames));
}

export function validateArrayOfType(...typeNames: NodeTypes[]) {
  return validate(arrayOfType(...typeNames));
}

export function assertEach(callback: Validator): Validator {
  const childValidator = process.env.BABEL_TYPES_8_BREAKING
    ? validateChild
    : () => {};

  function validator(node: t.Node, key: string, val: any) {
    if (!Array.isArray(val)) return;

    let i = 0;
    // For performance
    const subKey = {
      toString() {
        return `${key}[${i}]`;
      },
    };

    for (; i < val.length; i++) {
      const v = val[i];
      callback(node, subKey, v);
      childValidator(node, subKey, v);
    }
  }
  validator.each = callback;
  return validator;
}

export function assertOneOf(...values: Array<any>): Validator {
  function validate(node: any, key: string, val: any) {
    if (!values.includes(val)) {
      throw new TypeError(
        `Property ${key} expected value to be one of ${JSON.stringify(
          values,
        )} but got ${JSON.stringify(val)}`,
      );
    }
  }

  validate.oneOf = values;

  return validate;
}

export const allExpandedTypes: {

Review comment (performance):
Can you expand a bit the comment here?
- concatenating the strings is expensive because we are actually concatenating a string and a number, so V8 cannot just create a "rope string" but has to allocate memory for the string resulting from the number
- this string is very rarely used, only in error paths, so we can skip the concatenation cost in most cases

Code after:
export function arrayOfType(...typeNames: NodeTypes[]) {
  return arrayOf(assertNodeType(...typeNames));
}

export function validateArrayOfType(...typeNames: NodeTypes[]) {
  return validate(arrayOfType(...typeNames));
}

export function assertEach(callback: Validator): Validator {
  const childValidator = process.env.BABEL_TYPES_8_BREAKING
    ? validateChild
    : () => {};

  function validator(node: t.Node, key: string, val: any) {
    if (!Array.isArray(val)) return;

    let i = 0;
    // We lazily concatenate strings here for performance reasons.
    // Concatenating the strings is expensive because we are actually concatenating a string and a number,
    // so V8 cannot just create a "rope string" but has to allocate memory for the string resulting from the number
    // This string is very rarely used, only in error paths, so we can skip the concatenation cost in most cases
    const subKey = {
      toString() {
        return `${key}[${i}]`;
      },
    };

    for (; i < val.length; i++) {
      const v = val[i];
      callback(node, subKey, v);
      childValidator(node, subKey, v);
    }
  }
  validator.each = callback;
  return validator;
}

export function assertOneOf(...values: Array<any>): Validator {
  function validate(node: any, key: string, val: any) {
    if (!values.includes(val)) {
      throw new TypeError(
        `Property ${key} expected value to be one of ${JSON.stringify(
          values,
        )} but got ${JSON.stringify(val)}`,
      );
    }
  }

  validate.oneOf = values;

  return validate;