Compiler assumptions

    Since Babel 7.13.0, you can specify an assumptions option in your configuration to tell Babel which assumptions it can make about your code, to better optimize the compilation result. Note: this replaces the various loose options in plugins in favor of top-level options that can apply to multiple plugins (RFC link).

    For example:

    When spreading or iterating an array-like object, assume that it implements a [Symbol.iterator] method with the same behavior of the native Array.prototype[Symbol.iterator], and thus directly iterate over its element by index.

    This can be useful, for example, to iterate DOM collections in older browsers.

    1. let images = $("img");
    2. for (const img of images) {
    3. console.log(img);
    4. }
    5. const copy = [...images];

    constantReexports

    When re-exporting a binding from a module, assume that it doesn’t change and thus it’s safe to directly export it, as if you were doing

    1. import { value as val } from "dep";
    2. export const value = val;

    NOTE: This also affects the transform-modules-umd and transform-modules-amd plugins.

      constantSuper

      The super class of a class can be changed at any time by using Object.setPrototypeOf, making it impossible for Babel to statically know it. When this option is enabled, Babel assumes that it’s never changed and thus it is always the value that was placed in the extends clause in the class declaration.

      1. class Child extends Base {
      2. method() {
      3. super.method(2);
      4. }
      5. }

      enumerableModuleMeta

      1. export const number = 2;

      ignoreFunctionLength

      Functions have a .length property that reflect the number of parameters up to the last non-default parameter. When this option is enabled, assume that the compiled code does not rely on this .length property.

      1. function fn(a, b = 2, c, d = 3) {
      2. return a + b + c + d;
      3. }

      ignoreToPrimitiveHint

      When using language features that might call the [Symbol.toPrimitive] method of objects, assume that they don’t change their behavior based on the hint parameter.

      iterableIsArray

      When using an iterable object (in array destructuring, for-of or spreads), assume that it is an array.

      1. const [first, ...rest] = obj;
      2. call(first, ...obj);
      3. let arr = [first, ...obj];
      4. for (const el of obj) {
      5. console.log(el);
      6. }

      Don’t use Object.freeze for the template object created for tagged template literals. This effectively means using the taggedTemplateLiteralLoose helper instead of taggedTemplateLiteral.

      1. let str = tag`a`;

      noClassCalls

      When transforming classes, assume that they are always instantiate with new and they are never called as functions.

      1. class Test {
      2. constructor() {
      3. this.x = 2;
      4. }
      5. }

      noDocumentAll

      When using operators that check for null or undefined, assume that they are never used with the special value document.all.

      1. let score = points ?? 0;
      2. let name = user?.name;

      noIncompleteNsImportDetection

      Assume that no own property of a module export object is observed before initialization. For example, when trying to access ns.foo, it will return undefined both with this assumption turned on or off. The difference is that Object.prototype.hasOwnProperty.call(ns, "foo") would return false when noIncompleteNsImportDetection: true.

      1. export var foo;

      noNewArrows

      Assume that the code never tries to instantiate arrow functions using new, which is disallowed according to the specification.

      1. let getSum = (a, b) => {
      2. return { sum: a + b }
      3. };

      When using rest patterns in object destructuring, assume that destructured objects don’t have symbol keys or that it’s not a problem if they are not copied.

      privateFieldsAsProperties

      Assume that “soft privacy” is enough for private fields, and thus they can be stored as public non-enumerable properties with an unique name (rather than using an external WeakMap). This makes debugging compiled private fields easier.

      1. class Foo {
      2. #method() {}
      3. #field = 2;
      4. run() {
      5. this.#method();
      6. this.#field++;
      7. }
      8. }

      Assume that getters, if present, don’t have side-effects and can be accessed multiple times.

      1. let a = obj;
      2. a.b?.();

      setClassMethods

      When declaring classess, assume that methods don’t shadow getters on the superclass and that the program doesn’t depend on methods being non-enumerable. Thus, it’s safe to assign methods rather than using Object.defineProperty.

      1. class Foo extends Bar {
      2. method() {}
      3. static check() {}
      4. }

      setComputedProperties

      When using computed object properties, assume that the object doesn’t contain properties that overwrite setter defined in the same object, and thus it’s safe to assign them rather than defining them using Object.defineProperty.

      1. let obj = {
      2. set name(value) {},
      3. [key]: val
      4. }

      setPublicClassFields

      When using public class fields, assume that they don’t shadow any getter in the current class, in its subclasses or in its superclass. Thus, it’s safe to assign them rather than using Object.defineProperty.

      1. class Test {
      2. field = 2;
      3. static staticField = 3;
      4. }

      setSpreadProperties

      When using object spread, assume that spreaded properties don’t trigger getters on the target object and thus it’s safe to assign them rather than defining them using Object.defineProperty.

      1. const result = {
      2. set name(value) {},
      3. ...obj,
      4. };

      skipForOfIteratorClosing

      When using for-of with an iterator, it should always be closed with .return() and with .throw() in case of an error. When this option is called Babel assumes that those methods are not defined or empty, and it avoids calling them.

      superIsCallableConstructor

      1. class Child extends Parent {
      2. constructor() {
      3. super(42);