import type { EmptyObject } from 'type-fest';
export interface JvmTypeRef {
    jvmType: string;
    genericArguments?: JvmTypeRef[];
}
export type AnnotationValue = AnnotationValue[] | JvmTypeRef | boolean | number | string | undefined;
export interface Annotation {
    jvmType: string;
    attributes?: Record<string, AnnotationValue>;
}
export interface ModelMetadata {
    jvmType?: string;
    annotations?: Annotation[];
}
export type Target<T = unknown> = {
    readonly model?: Model<T>;
    readonly value: T;
};
export declare const nothing: unique symbol;
export declare enum Enum {
}
export type AnyObject = Readonly<Record<never, never>>;
export declare const $key: unique symbol;
export declare const $name: unique symbol;
export declare const $owner: unique symbol;
export declare const $meta: unique symbol;
export declare const $optional: unique symbol;
export declare const $defaultValue: unique symbol;
export declare const $constraints: unique symbol;
export declare const $members: unique symbol;
export type Value<M extends Model> = M extends Model<infer T> ? T : never;
export type Extensions<M extends Model> = M extends Model<unknown, infer EX> ? EX : AnyObject;
export declare const $assertSupportedModel: unique symbol;
export type ConstraintFn<V = unknown, A extends AnyObject = AnyObject> = EmptyObject extends A ? (attributes?: A) => Constraint<V> : {
    readonly value: never;
} extends A ? (valueOrAttributes: (A & {
    readonly value: unknown;
})['value'] | A) => Constraint<V> : (attributes: A) => Constraint<V>;
export type NonAttributedConstraint<V = unknown, N extends string = string, A extends AnyObject = AnyObject> = ConstraintFn<V, A> & Readonly<{
    attributes: A;
    name: N;
    [$assertSupportedModel](model: Model<V>): void;
}>;
export type Constraint<V = unknown, N extends string = string, A extends AnyObject = AnyObject> = Readonly<{
    attributes: EmptyObject extends A ? A : Required<A>;
    name: N;
    [$assertSupportedModel](model: Model<V>): void;
}>;
export type Model<V = unknown, EX extends AnyObject = AnyObject> = EX & {
    readonly [$key]: keyof any;
    readonly [$name]: string;
    readonly [$owner]: Model | Target;
    readonly [$meta]?: ModelMetadata;
    readonly [$optional]: boolean;
    readonly [$constraints]: readonly Constraint[];
    readonly [$defaultValue]: V;
    readonly [Symbol.toStringTag]: string;
    [Symbol.hasInstance](value: any): value is Model<V, EX>;
    toString(): string;
};
export type DefaultValueProvider<V, EX extends AnyObject = AnyObject> = (model: Model<V, EX>) => V;
export declare const Model: Model;
export declare const $sourceModel: unique symbol;
export declare const $targetModel: unique symbol;
export type ModelConverter<SM extends Model = Model, TM extends Model = Model> = {
    readonly [$sourceModel]: SM;
    readonly [$targetModel]: TM;
};
export type SourceModel<MC extends ModelConverter> = MC[typeof $sourceModel];
export type TargetModel<MC extends ModelConverter, SM extends SourceModel<MC>> = (MC & {
    readonly [$sourceModel]: SM;
})[typeof $targetModel];
export interface CompositeOf<A extends ModelConverter, B extends ModelConverter<Model, SourceModel<A>>> extends ModelConverter<SourceModel<B>> {
    readonly [$targetModel]: TargetModel<A, TargetModel<B, SourceModel<this>>>;
}
