Core
Namespace
Full Namespace
declare namespace Model {
  /** Any type of Model, using own class constructor as its identifier. */
type Type<T extends Model = Model> = abstract new (...args: any[]) => T
 
  /** A type of Model which may be created without constructor arguments. */
type New<T extends Model = Model> = (new () => T) & typeof Model;
 
  /** Subset of `keyof T` which are not methods or defined by base Model U. **/
type Field<T> = Exclude<keyof T, keyof Model>;
 
type Key<T> = Field<T> | (string & {}) | number | symbol;
 
  /** Actual value stored in state. */
type Actual<R> =
    R extends Ref<infer T> ? T :
    R extends Model ? State<R> :
    R;
 
type Value<T extends Model, K extends Key<T>> =
    K extends string | number | symbol ? T[K] extends Ref<infer V> ? V : T[K] : unknown;
 
type OnUpdate<T extends Model, K extends Key<T>> =
    (this: T, value: Value<T, K>, key: K, thisArg: K) => void;
 
  /**
   * Values from current state of given controller.
   * Differs from `Values` as values here will drill
   * into "real" values held by exotics like ref.
   */
type State<T> = { [P in Field<T>]: Actual<T[P]> };
 
  /** Object comparable to data found in T. */
type Values<T> = { [P in Field<T>]?: Actual<T[P]> };
 
  /** Exotic value, where actual value is contained within. */
type Ref<T = any> = {
    (next: T): void;
    current: T | null;
  }
 
  /** A callback function which is subscribed to parent and updates when values change. */
type Effect<T> = (this: T, argument: T) => ((update: boolean | null) => void) | Promise<void> | null | void;
 
type Event<T extends Model> =
    (this: T, key: unknown, source: T) => (() => void) | void | null;
 
  namespace Instruction {
  type Getter<T> = (source: Model) => T;
  type Setter<T> = (value: T, previous: T) => boolean | void | (() => T);
 
  type Descriptor<T = any> = {
      get?: Getter<T> | boolean;
      set?: Setter<T> | false;
      enumerable?: boolean;
      value?: T;
    }
  }
 
  /**
   * Property initializer, will run upon instance creation.
   * Optional returned callback will run when once upon first access.
   */
type Instruction<T = any, M extends Model = any> =
    // TODO: Should this allow for numbers/symbol properties?
    (this: M, key: Model.Field<M> & string, thisArg: M, state: Model.State<M>) =>
      Instruction.Descriptor<T> | Instruction.Getter<T> | void;
}

Type

Any type of Model, using own class constructor as its identifier.


type Type<T extends Model = Model> = abstract new (...args: any[]) => T;

New

A type of Model which may be created without constructor arguments.


type New<T extends Model = Model> = (new () => T) & typeof Model;

Field

Subset of keyof T which are not methods or defined by base Model U.


type Field<T> = Exclude<keyof T, keyof Model>;

Key

Any acceptable event. This includes any field of T, for purposes of autocomplete, while string, number, and symbol are also valid.


type Key<T> = Field<T> | (string & {}) | number | symbol;

Actual

Actual value stored in state. This unwraps any exotic values like Ref whose value is not what is returned by its given property.


type Actual<R> = R extends Ref<infer T> ? T : R extends Model ? State<R> : R;

Value

Value of given key, unwrapping any exotic values like Ref whose value is not what is returned by its given property.


type Value<T extends Model, K extends Key<T>> =
    K extends keyof T ? T[K] extends Ref<infer V> ? V : T[K] : unknown;