export type TList = {
    type: 'array';
    items: TSchema;
    required: boolean;
    validator?: (v: any[]) => void;
};
export type TObject = {
    type: 'object';
    properties: Record<string, TSchema>;
    required: boolean;
    validator?: (v: Record<any, any>) => void;
};
export type THashMap = {
    type: 'hashMap';
    property: TSchema;
    required: boolean;
    validator?: (v: any[]) => void;
};
export type TBoolean = {
    type: 'boolean';
    required: boolean;
    validator?: (v: boolean) => void;
};
export type TString = {
    type: 'string';
    required: boolean;
    validator?: (v: string) => void;
};
export type TNumber = {
    type: 'number';
    required: boolean;
    validator?: (v: number) => void;
};
export type TTransform = {
    type: 'transformType';
    encodedTSchema: TSchema;
    decodedTSchema: TSchema;
    syncDecoder: (val: any) => any;
    syncEncoder: (val: any) => any;
    required: boolean;
    validator?: (v: any) => void;
};
export type TAny = {
    type: 'any';
    required: boolean;
    validator?: (v: any) => void;
};
export type TEnum = {
    type: 'enum';
    required: boolean;
    options: any[];
    validator?: (v: any) => void;
};
export type TOneOf = {
    type: 'oneOf';
    required: boolean;
    options: any[];
    validator?: (v: any) => void;
};
export type TLazy = {
    type: 'lazy';
    name: string;
    required: boolean;
    validator?: (v: any) => void;
    getSchema: () => any;
};
export type TSchema = TLazy | TList | TObject | TString | TNumber | TBoolean | TAny | TEnum | TTransform | TOneOf | THashMap;
type MakeTOptional<T, Required extends boolean> = Required extends true ? T : T | undefined | null;
type GetValues<T> = T extends Record<any, infer Values> ? Values : never;
type GetFilterRequiredKeysUnion<T extends Record<any, {
    required: boolean;
}>, IsRequired extends boolean, EnhancedObjects = {
    [K in keyof T]: T[K] & {
        key: K;
    };
}, T1 = GetValues<EnhancedObjects> & {
    required: IsRequired;
}, T2 = T1['key']> = T2;
type InferObjWithOptKeysObject<Properties extends TObject['properties'], TT extends 'encoded' | 'decoded', ReqKeys = GetFilterRequiredKeysUnion<Properties, true>, OptKeys = GetFilterRequiredKeysUnion<Properties, false>, ReqObjPart = {
    [K in ReqKeys]: InferSchemaTypeEncDec<Properties[K], TT>;
}, OptObjPart = {
    [K in OptKeys]?: InferSchemaTypeEncDec<Properties[K], TT>;
}, Out = ReqObjPart & OptObjPart> = Out;
export type InferSchemaTypeEncDec<T extends TSchema | undefined, TT extends 'encoded' | 'decoded'> = T extends undefined ? undefined : T extends {
    type: 'object';
} ? MakeTOptional<InferObjWithOptKeysObject<T['properties'], TT>, T['required']> : T extends {
    type: 'array';
    items: any;
} ? MakeTOptional<InferSchemaTypeEncDec<T['items'], TT>[], T['required']> : T extends {
    type: 'boolean';
} ? MakeTOptional<boolean, T['required']> : T extends {
    type: 'string';
} ? MakeTOptional<string, T['required']> : T extends {
    type: 'oneOf';
} ? MakeTOptional<InferSchemaTypeEncDec<T['options'][number], TT>, T['required']> : T extends {
    type: 'enum';
} ? MakeTOptional<T['options'][number], T['required']> : T extends {
    type: 'number';
} ? MakeTOptional<number, T['required']> : T extends {
    type: 'hashMap';
} ? MakeTOptional<Record<string, InferSchemaTypeEncDec<T['property'], TT>>, T['required']> : T extends {
    type: 'lazy';
} ? any : T extends {
    type: 'transformType';
} ? TT extends 'decoded' ? MakeTOptional<ReturnType<T['syncDecoder']>, T['required']> : TT extends 'encoded' ? MakeTOptional<ReturnType<T['syncEncoder']>, T['required']> : never : T extends {
    type: 'any';
} ? any : never;
export type InferSchemaType<T extends TSchema | undefined> = InferSchemaTypeEncDec<T, 'decoded'>;
export type InferEncodedSchemaType<T extends TSchema | undefined> = InferSchemaTypeEncDec<T, 'encoded'>;
export {};
