type PathParams<T, Rest> = {
    first: T;
    rest: Rest;
};
type AnyObject = Record<string, unknown>;
type AcceptNullable<T> = Exclude<T, null | undefined>;
type SanitizeKey<Key, DoSanitize extends boolean> = DoSanitize extends true ? Key extends `${string}.${string}` ? `(${Key})` : Key & string : Key;
type Join<Prefix extends string = '', Key extends string = '', DoSanitize extends boolean = true> = `${Prefix}${SanitizeKey<Key, DoSanitize>}`;
type Matcher<Type, KeyPath extends string, ExpectedType, PreventDistribution extends boolean> = PreventDistribution extends true ? [Type] extends [ExpectedType] ? KeyPath : never : Type extends ExpectedType ? KeyPath : never;
/**
 * @example ```ts
 *  type Input = { one: { subone: { subonetwo: string; } } };
 *
 *  type OutputOne = AddProp<Input, 'one.subone.subonethree', number>;
 *  declare const outputOne: OutputOne;
 *  outputOne.one.subone.subonethree = 5;
 *
 *  type OutputTwo = AddProp<Input, 'two', string>;
 *  declare const outputTwo: OutputTwo;
 *  outputTwo.two = 'str';
 * ```
 */
type AddProp<T extends AnyObject, Path extends string, TargetType, Params extends PathParams<any, any> = Split<Path>> = T & Record<Params['first'], Params['rest'] extends undefined ? TargetType : T[Params['first']] extends AnyObject ? Params['rest'] extends `(${infer A})` ? T[Params['first']] & Record<A, TargetType> : AddProp<T[Params['first']], Params['rest'], TargetType> : Record<Params['rest'], TargetType>>;
type Split<T extends string> = (T extends `(${infer A}).${infer Rest}` ? PathParams<A, Rest> : T extends `${infer A}.${infer Rest}` ? PathParams<A, Rest> : PathParams<T, undefined>);

type ObjectPaths<T, ExpectedType, PreventDistribution extends boolean, Prefix extends string = ""> = T extends never ? never : {
    [K in keyof T & string]: AcceptNullable<T[K]> extends AnyObject ? Matcher<T[K], Join<Prefix, K>, ExpectedType, PreventDistribution> | ObjectPaths<AcceptNullable<T[K]>, ExpectedType, PreventDistribution, `${Join<Prefix, K>}.`> : Matcher<T[K], Join<Prefix, K>, ExpectedType, PreventDistribution>;
}[keyof T & string];
type ExtractObjectPaths<T, ExpectedType = DefaultTypedotsParams['expectedType'], PreventDistribution extends boolean = DefaultTypedotsParams['preventDistribution']> = ObjectPaths<T, ExpectedType, PreventDistribution>;

type GetMethod<P extends TypedotsParams = DefaultTypedotsParams> = <BaseObject extends AnyObject, Path extends ExtractObjectPaths<BaseObject, P['expectedType'], P['preventDistribution']>>(object: BaseObject, path: Path) => undefined | any;

type UpdateApplied = boolean;

type HasMethod<P extends TypedotsParams = DefaultTypedotsParams> = <BaseObject extends AnyObject, Path extends ExtractObjectPaths<BaseObject, P['expectedType'], P['preventDistribution']>>(object: BaseObject, path: Path) => boolean;

declare const get: GetMethod;

declare const set: <BaseObject extends AnyObject, Path extends Force extends true ? ExtractObjectPaths<BaseObject, any, true> | string : ExtractObjectPaths<BaseObject, any, true>, Value, Force extends boolean = false>(object: BaseObject, path: Path, value: Value, force?: Force) => object is Force extends true ? Prettify<AddProp<BaseObject, Path, typeof value>> : BaseObject;
type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};

declare const has: HasMethod;

interface TypedotsParams {
    expectedType?: any;
    preventDistribution: boolean;
}
type DefaultTypedotsParams = TypedotsParams & {
    expectedType: any;
    preventDistribution: false;
};
declare class BaseTypedots<P extends TypedotsParams> {
    get: GetMethod<P>;
    set: typeof set;
    has: HasMethod<P>;
}

declare class Typedots<P extends TypedotsParams> implements BaseTypedots<P> {
    get: GetMethod<P>;
    set: <BaseObject extends AnyObject, Path extends Force extends true ? ExtractObjectPaths<BaseObject, any, true> | string : ExtractObjectPaths<BaseObject, any, true>, Value, Force extends boolean = false>(object: BaseObject, path: Path, value: Value, force?: Force) => object is Force extends true ? AddProp<BaseObject, Path, Value> extends infer T ? { [K in keyof T]: AddProp<BaseObject, Path, Value>[K]; } : never : BaseObject;
    has: HasMethod<P>;
}

export { BaseTypedots, type DefaultTypedotsParams, type ExtractObjectPaths, type GetMethod, type HasMethod, type TypedotsParams, type UpdateApplied, Typedots as default, get, has, set };
