declare module '@glimmer/tracking' {
    export { tracked } from "@ember/-internals/metal/lib/tracked";
    export { cached } from "@ember/-internals/metal/lib/cached";
    export type { Reactive, ReadOnlyReactive, TrackedValue, } from "@glimmer/validator/lib/tracked-value";
    /**
      In order to tell Ember a value might change, we need to mark it as trackable.
      Trackable values are values that:

      - Can change over their component’s lifetime and
      - Should cause Ember to rerender if and when they change

      We can do this by marking the field with the `@tracked` decorator.

      @module @glimmer/tracking
      @public
    */
    /**
      Marks a property as tracked. By default, values that are rendered in Ember app
      templates are _static_, meaning that updates to them won't cause the
      application to rerender. Marking a property as tracked means that when that
      property changes, any templates that used that property, directly or
      indirectly, will rerender. For instance, consider this component:

      ```gjs
      import Component from '@glimmer/component';
      import { tracked } from '@glimmer/tracking';
      import { action } from '@ember/object';

      export default class CounterComponent extends Component {
        @tracked count = 0;

        get timesTen() {
          return this.count * 10;
        }

        @action
        plusOne() {
          this.count += 1;
        }

        <template>
          <div>Count: {{this.count}}</div>
          <div>Times Ten: {{this.timesTen}}</div>
          <div>
            <button {{on "click" this.plusOne}}>
              Plus One
            </button>
          </div>
        </template>
      }
      ```

      Both the `{{this.count}}` and the `{{this.timesTen}}` properties in the
      template will update whenever the button is clicked. Any tracked properties
      that are used in any way to calculate a value that is used in the template
      will cause a rerender when updated - this includes through method calls and
      other means:

      ```gjs
      import Component from '@glimmer/component';
      import { tracked } from '@glimmer/tracking';

      class Entry {
        @tracked name;
        @tracked phoneNumber;

        constructor(name, phoneNumber) {
          this.name = name;
          this.phoneNumber = phoneNumber;
        }
      }

      export default class PhoneBookComponent extends Component {
        entries = [
          new Entry('Pizza Palace', 5551234),
          new Entry('1st Street Cleaners', 5554321),
          new Entry('Plants R Us', 5552468),
        ];

        // Any usage of this property will update whenever any of the names in the
        // entries arrays are updated
        get names() {
          return this.entries.map(e => e.name);
        }

        // Any usage of this property will update whenever any of the numbers in the
        // entries arrays are updated
        get numbers() {
          return this.getFormattedNumbers();
        }

        getFormattedNumbers() {
          return this.entries
            .map(e => e.phoneNumber)
            .map(number => {
              let numberString = '' + number;

              return numberString.slice(0, 3) + '-' + numberString.slice(3);
            });
        }
      }
      ```

      It's important to note that setting tracked properties will always trigger an
      update, even if the property is set to the same value as it was before.

      ```js
      let entry = new Entry('Pizza Palace', 5551234);
      // if entry was used when rendering, this would cause a rerender, even though
      // the name is being set to the same value as it was before
      entry.name = entry.name;
      ```

      `tracked` can also be used with the classic Ember object model in a similar
      manner to classic computed properties:

      ```javascript
      import EmberObject from '@ember/object';
      import { tracked } from '@glimmer/tracking';

      const Entry = EmberObject.extend({
        name: tracked(),
        phoneNumber: tracked()
      });
      ```

      Often this is unnecessary, but to ensure robust auto-tracking behavior it is
      advisable to mark tracked state appropriately wherever possible.
      This form of `tracked` also accepts an optional configuration object
      containing either an initial `value` or an `initializer` function (but not
      both).

      ```javascript
      import EmberObject from '@ember/object';
      import { tracked } from '@glimmer/tracking';

      const Entry = EmberObject.extend({
        name: tracked({ value: 'Zoey' }),
        favoriteSongs: tracked({
          initializer: () => ['Raspberry Beret', 'Time After Time']
        })
      });
      ```

      Calling `tracked` with an initial value creates a standalone reactive
      value, usable outside of classes:

      ```js
      import { tracked } from '@glimmer/tracking';

      const count = tracked(0);

      count.value;                // read the value, entangling with any tracking context
      count.value = 1;            // write the value, notifying consumers
      count.get();                // function shorthand for reading
      count.set(2);               // function shorthand for writing
      count.update((n) => n + 1); // write based on the current value, without entangling
      count.freeze();             // prevent all future writes
      ```

      Reading `value` in a template (or in a getter used by a template) will
      rerender just like a `@tracked` property:

      ```gjs
      import { tracked } from '@glimmer/tracking';
      import { on } from '@ember/modifier';

      const count = tracked(0);
      const increment = () => count.value++;

      <template>
        Count is: {{count.value}}

        <button {{on "click" increment}}>add one</button>
      </template>
      ```

      This form accepts an options object containing an `equals` function, which
      decides whether a written value should notify consumers (it defaults to
      `Object.is`), and a `description` used for debugging:

      ```js
      const count = tracked(0, { equals: (a, b) => a === b });

      count.value = 0; // does not notify consumers, the value did not change
      ```

      Note: when `tracked` is called with a single plain object whose keys are all
      drawn from `value`, `initializer`, `equals`, and `description`, it is treated
      as the configuration object for a decorator (or classic-class field), not as a
      standalone value wrapping that object. To create a standalone reactive value
      around such an object, pass it as an initial value and include a (possibly
      empty) options argument: `tracked({ value: 5 }, {})`.

      The `@tracked` decorator accepts the same options. By default, setting a
      `@tracked` property always notifies consumers, even when setting the
      property to the same value; passing `equals` opts in to equality-based
      notification instead:

      ```js
      import { tracked } from '@glimmer/tracking';

      class Counter {
        @tracked({ equals: (a, b) => a === b }) count = 0;

        noop = () => {
          // does not notify consumers, the value did not change
          this.count = this.count;
        };
      }
      ```

      @method tracked
      @static
      @for @glimmer/tracking
      @public
    */
    /**
      The `@cached` decorator can be used on getters in order to cache the return
      value of the getter. This is useful when a getter is expensive and used very
      often. For instance, in this guest list class, we have the `sortedGuests`
      getter that sorts the guests alphabetically:

      ```js
      import { tracked } from '@glimmer/tracking';

      class GuestList {
        @tracked guests = ['Zoey', 'Tomster'];

        get sortedGuests() {
          return this.guests.slice().sort()
        }
      }
      ```

      Every time `sortedGuests` is accessed, a new array will be created and sorted,
      because JavaScript getters do not cache by default. When the guest list is
      small, like the one in the example, this is not a problem. However, if the guest
      list were to grow very large, it would mean that we would be doing a large
      amount of work each time we accessed `sortedGetters`. With `@cached`, we can
      cache the value instead:

      ```js
      import { tracked, cached } from '@glimmer/tracking';

      class GuestList {
        @tracked guests = ['Zoey', 'Tomster'];

        @cached
        get sortedGuests() {
          return this.guests.slice().sort()
        }
      }
      ```

      Now the `sortedGuests` getter will be cached based on _autotracking_. It will
      only rerun and create a new sorted array when the `guests` tracked property is
      updated.

      In general, you should avoid using `@cached` unless you have confirmed that the
      getter you are decorating is computationally expensive. `@cached` adds a small
      amount of overhead to the getter, making it more expensive. While this overhead
      is small, if `@cached` is overused it can add up to a large impact overall in
      your app. Many getters and tracked properties are only accessed once, rendered,
      and then never rerendered, so adding `@cached` when it is unnecessary can
      negatively impact performance.

      @method cached
      @static
      @for @glimmer/tracking
      @public
     */
}