import { type BinderNode } from './BinderNode.js';
import type { Validator } from './Validation.js';
export declare const _createEmptyItemValue: unique symbol;
export declare const _parent: unique symbol;
export declare const _key: unique symbol;
export declare const _fromString: unique symbol;
export declare const _validators: unique symbol;
export declare const _meta: unique symbol;
export declare const _getPropertyModel: unique symbol;
export declare const _enum: unique symbol;
export declare const _items: unique symbol;
declare const _optional: unique symbol;
export interface HasFromString<T> {
    [_fromString](value: string): T;
}
export declare function hasFromString<T>(model: AbstractModel<T>): model is AbstractModel<T> & HasFromString<T>;
export type Value<M> = M extends AbstractModel<infer T> ? T : never;
export declare const modelDetachedParent: {
    $value$: undefined;
};
export type ModelParent = AbstractModel | BinderNode | typeof modelDetachedParent;
export interface Annotation {
    name: string;
    attributes?: Record<string, unknown>;
}
export interface ModelMetadata {
    javaType?: string;
    annotations?: Annotation[];
}
export interface ModelOptions<T> {
    validators?: ReadonlyArray<Validator<T>>;
    meta?: ModelMetadata;
}
export type DetachedModelConstructor<M> = {
    prototype: object;
    new (parent: typeof modelDetachedParent, key: '$value$', optional: boolean): M;
};
export declare function createDetachedModel<M extends AbstractModel>(type: DetachedModelConstructor<M>): M;
export declare abstract class AbstractModel<T = unknown> {
    static createEmptyValue(): unknown;
    readonly ['constructor']: typeof AbstractModel<T>;
    readonly [_parent]?: ModelParent;
    readonly [_validators]: ReadonlyArray<Validator<T>>;
    readonly [_meta]: ModelMetadata;
    readonly [_optional]: boolean;
    [_key]: keyof any;
    constructor(parent: ModelParent, key: keyof any, optional: boolean, options?: ModelOptions<T>);
    toString(): string;
    valueOf(): T;
}
export declare abstract class PrimitiveModel<T> extends AbstractModel<T> {
}
export declare class BooleanModel extends PrimitiveModel<boolean> implements HasFromString<boolean> {
    static createEmptyValue: BooleanConstructor;
    [_fromString](str: string): boolean;
}
export declare class NumberModel extends PrimitiveModel<number> implements HasFromString<number | undefined> {
    static createEmptyValue(): number;
    constructor(parent: ModelParent, key: keyof any, optional: boolean, options?: ModelOptions<number>);
    [_fromString](str: string): number | undefined;
}
export declare class StringModel extends PrimitiveModel<string> implements HasFromString<string> {
    static createEmptyValue: StringConstructor;
    [_fromString]: StringConstructor;
}
declare enum Enum {
}
export declare function makeEnumEmptyValueCreator<M extends EnumModel>(type: DetachedModelConstructor<M>): () => Value<M>;
export declare abstract class EnumModel<E extends typeof Enum = typeof Enum> extends AbstractModel<E[keyof E]> implements HasFromString<E[keyof E] | undefined> {
    abstract readonly [_enum]: E;
    [_fromString](value: string): E[keyof E] | undefined;
}
export declare function getObjectModelOwnAndParentGetters<M extends ObjectModel>(model: M): Generator<readonly [key: keyof Value<M>, getter: () => AbstractModel]>;
export declare function makeObjectEmptyValueCreator<M extends ObjectModel>(type: DetachedModelConstructor<M>): () => Value<M>;
type ChildModel<T extends Record<never, never>, K extends keyof T> = AbstractModel<NonNullable<T[K]>>;
export declare class ObjectModel<T extends Record<never, never> = Record<never, never>> extends AbstractModel<T> {
    #private;
    static createEmptyValue: () => Record<never, never>;
    protected [_getPropertyModel]<K extends keyof T, M extends ChildModel<T, K>>(key: K, init: (parent: this, key: K) => M): M;
}
export type ArrayItemModel<M> = M extends ArrayModel<infer MItem> ? MItem : never;
export declare class ArrayModel<MItem extends AbstractModel = AbstractModel> extends AbstractModel<Array<Value<MItem>>> {
    #private;
    static createEmptyValue(): [];
    [_createEmptyItemValue]: () => Value<MItem>;
    constructor(parent: ModelParent, key: keyof any, optional: boolean, createItem: (parent: AbstractModel, key: number) => MItem, options?: ModelOptions<Array<Value<MItem>>>);
    [_items](): Generator<MItem, void, void>;
    [Symbol.iterator](): IterableIterator<BinderNode<MItem>>;
}
export declare const m: {
    items<M extends ArrayModel>(model: M): Generator<ArrayItemModel<M>, void, void>;
};
export {};
