declare module '@ember-data/model/-private/attr' {
  import type { ArrayValue, ObjectValue, PrimitiveValue } from '@warp-drive/core-types/json/raw';
  import type { TransformName } from '@warp-drive/core-types/symbols';
  import type { DecoratorPropertyDescriptor } from '@ember-data/model/-private/util';
  /**
   * Options provided to the attr decorator are
   * supplied to the associated transform. Any
   * key-value pair is valid; however, it is highly
   * recommended to only use statically defined values
   * that could be serialized to JSON.
   *
   * If no transform is provided, the only valid
   * option is `defaultValue`.
   *
   * Examples:
   *
   * ```ts
   * class User extends Model {
   *  @attr('string', { defaultValue: 'Anonymous' }) name;
   *  @attr('date', { defaultValue: () => new Date() }) createdAt;
   *  @attr({ defaultValue: () => ({}) }) preferences;
   *  @attr('boolean') hasVerifiedEmail;
   *  @attr address;
   * }
   *
   * @class NOTATHING
   */
  export type AttrOptions<DV = PrimitiveValue | object | unknown[]> = {
      /**
       * The default value for this attribute.
       *
       * Default values can be provided as a value or a function that will be
       * executed to generate the default value.
       *
       * Default values *should not* be stateful (object, arrays, etc.) as
       * they will be shared across all instances of the record.
       *
       */
      defaultValue?: DV extends PrimitiveValue ? DV : () => DV;
  };
  type LooseTransformInstance<V, Raw, Name extends string> = {
      /**
       * value type must match the return type of the deserialize method
       *
       */
      serialize: (value: V, options: any) => Raw;
      /**
       * defaultValue type must match the return type of the deserialize method
       *
       */
      deserialize: (value: Raw, options: any) => V;
      [TransformName]: Name;
  };
  export type TransformHasType = {
      [TransformName]: string;
  };
  export type TypedTransformInstance<V, T extends string> = LooseTransformInstance<V, string, T> | LooseTransformInstance<V, number, T> | LooseTransformInstance<V, boolean, T> | LooseTransformInstance<V, null, T> | LooseTransformInstance<V, ObjectValue, T> | LooseTransformInstance<V, ArrayValue, T> | LooseTransformInstance<V, string | null, T> | LooseTransformInstance<V, number | null, T> | LooseTransformInstance<V, boolean | null, T> | LooseTransformInstance<V, ObjectValue | null, T> | LooseTransformInstance<V, ArrayValue | null, T>;
  export type GetMaybeDeserializeValue<T> = T extends {
      deserialize: (...args: any[]) => unknown;
  } ? ReturnType<T['deserialize']> : never;
  export type TypeFromInstance<T> = T extends TransformHasType ? T[typeof TransformName] : never;
  export type ExtractOptions<T extends TypedTransformInstance<GetMaybeDeserializeValue<T>, TypeFromInstance<T>>> = Parameters<T['deserialize']>[1] & Parameters<T['serialize']>[1] & AttrOptions<ReturnType<T['deserialize']>>;
  export type OptionsFromInstance<T> = TypeFromInstance<T> extends never ? never : GetMaybeDeserializeValue<T> extends never ? never : T extends TypedTransformInstance<GetMaybeDeserializeValue<T>, TypeFromInstance<T>> ? Parameters<T['deserialize']>[1] & Parameters<T['serialize']>[1] & AttrOptions<ReturnType<T['deserialize']>> : never;
  /**
   * The return type of `void` is a lie to appease TypeScript. The actual return type
   * is a descriptor, but typescript incorrectly insists that decorator functions return
   * `void` or `any`.
   *
   */
  export type DataDecorator = (target: object, key: string, desc?: DecoratorPropertyDescriptor) => void;
  /**
    `attr` defines an attribute on a [Model](/ember-data/release/classes/Model).
    By default, attributes are passed through as-is, however you can specify an
    optional type to have the value automatically transformed.
    EmberData ships with four basic transform types: `string`, `number`,
    `boolean` and `date`. You can define your own transforms by subclassing
    [Transform](/ember-data/release/classes/Transform).
  
    Note that you cannot use `attr` to define an attribute of `id`.
  
    `attr` takes an optional hash as a second parameter, currently
    supported options are:
  
    - `defaultValue`: Pass a string or a function to be called to set the attribute
    to a default value if and only if the key is absent from the payload response.
  
    Example
  
    ```js [app/models/user.js]
    import Model, { attr } from '@ember-data/model';
  
    export default class UserModel extends Model {
      @attr('string') username;
      @attr('string') email;
      @attr('boolean', { defaultValue: false }) verified;
    }
    ```
  
    Default value can also be a function. This is useful it you want to return
    a new object for each attribute.
  
    ```js [app/models/user.js]
    import Model, { attr } from '@ember-data/model';
  
    export default class UserModel extends Model {
      @attr('string') username;
      @attr('string') email;
  
      @attr({
        defaultValue() {
          return {};
        }
      })
      settings;
    }
    ```
  
    The `options` hash is passed as second argument to a transforms'
    `serialize` and `deserialize` method. This allows to configure a
    transformation and adapt the corresponding value, based on the config:
  
    ```js [app/models/post.js]
    import Model, { attr } from '@ember-data/model';
  
    export default class PostModel extends Model {
      @attr('text', {
        uppercase: true
      })
      text;
    }
    ```
  
    ```js [app/transforms/text.js]
    export default class TextTransform {
      serialize(value, options) {
        if (options.uppercase) {
          return value.toUpperCase();
        }
  
        return value;
      }
  
      deserialize(value) {
        return value;
      }
  
      static create() {
        return new this();
      }
    }
    ```
  
    @public
    @param {String|Object} type the attribute type
    @param {Object} options a hash of options
    @return {Attribute}
  */
  export function attr(): DataDecorator;
  export function attr<T>(type: TypeFromInstance<T>): DataDecorator;
  export function attr(type: string): DataDecorator;
  export function attr(options: AttrOptions): DataDecorator;
  export function attr<T>(type: TypeFromInstance<T>, options?: OptionsFromInstance<T>): DataDecorator;
  export function attr(type: string, options?: AttrOptions & object): DataDecorator;
  export function attr(target: object, key: string | symbol, desc?: PropertyDescriptor): void;
  export {};
}
//# sourceMappingURL=attr.d.ts.map