/**
 * Type signature for data object constructor functions.
 * Creates a function that accepts partial data and returns complete typed objects.
 * @template T - The object type to be constructed
 * @param [o] - Optional partial input data
 * @returns A complete object of type T
 * @category Core Implementation
 */
declare type DataConstructor<T extends object> = (o?: Expect<T>) => T;

/**
 * Creates a TypeScript type guard function for runtime type validation.
 *
 * Generates a type-safe validation function that:
 * - Performs runtime type checking
 * - Provides TypeScript type assertions
 * - Supports partial input validation based on predicate
 *
 *
 * @example
 * ```typescript
 * import { dataGuard } from 'ts-data-objects/core'
 * import { isStr, isNum } from 'ts-data-objects/common'
 *
 * type UserData = {
 *   name: string
 *   age: number
 *   verified?: boolean
 * }
 *
 * // Here we define a function predicate, where `o` is the JSON object
 * // and we expect it to contain the attributes of the types we expect
 * const isUserData = dataGuard<UserData>(o => (
 *   isStr(o?.name) &&
 *   isNum(o?.age)
 * ))
 *
 * // Usage:
 * if (isUserData(someData)) {
 *   //TypeScript now knows `someData` is `UserData`
 *   console.log(someData.name)
 * }
 * ```
 *
 * @template T - The object type to create a guard for
 * @param predicate - Validation function that checks type constraints
 * @returns A type guard function that asserts input is of type T
 * @category Core Component
 */
export declare const dataGuard: <T extends object>(predicate: GuardPredicate<T>) => DataObjectGuard<T>;

/**
 * Creates a typed constructor function for data objects with optional default values.
 *
 * This function generates a constructor that:
 * - Enforces TypeScript type safety
 * - Merges default values with provided data
 * - Handles partial input data
 *
 *
 * @example
 * ```typescript
 * import { dataObject } from 'ts-data-objects/core'
 *
 * type UserData = {
 *   name: string
 *   age: number
 *   verified?: boolean
 * }
 *
 * // Here you can optionally define any default values
 * // that you might want to be included when parsing JSON data
 * // or just creating JS Object from scratch
 * const User = dataObject<UserData>({
 *   name: '',
 *   verified: false
 * })
 *
 * // Usage:
 * const user = User({ name: "John", age: 20 })
 * // Result: { name: "John", , age: 20, verified: false }
 * ```
 *
 * Notes:
 * - Name collision with TS interface is possible and will work
 * - The constructor performs shallow merge of objects! This means
 * that nested objects are replaced rather than copied
 *
 * ---
 *
 * @template T - The object type/interface to create a constructor for
 * @param [defaultValues] - Optional default values for the object properties
 * @returns A constructor function that creates objects of type T
 * @category Core Component
 */
export declare const dataObject: <T extends object>(defaultValues?: Expect<T>) => DataConstructor<T>;

/**
 * Type signature for type guard functions that provide TypeScript type assertions.
 *
 * Note:
 * - As pure predicate wouldn't be able to have assertion return type `returnValue is SomeType`, the predicates are wrapped in guard assertions
 *
 * @template T - The object type to guard
 * @param [o] - Optional partial input data to check
 * @returns Type predicate asserting the input is of type T
 * @category Core Component
 */
declare type DataObjectGuard<T extends object> = (o?: Expect<T>) => o is T;

/**
 * Creates a type-safe parser that validates and constructs data objects.
 *
 * Combines validation and construction into a single function that:
 * - Validates input data against type constraints
 * - Constructs a proper typed object if valid
 * - Handles validation failures
 *
 * @example
 * ```typescript
 * import { dataParser } from 'ts-data-objects/core'
 *
 * type UserData = {
 *   name: string
 *   age: number
 *   verified?: boolean
 * }
 *
 * // ... with defined constructor and data guard ...
 *
 * const parseUser = dataParser<UserData>(
 *   'UserData',
 *   UserData,        // constructor from dataObject
 *   isUserData,      // guard from dataGuard
 * )
 *
 * // Usage:
 * const user = parseUser(someData) // throws if invalid
 * // If the code continues, it was successfully parsed
 * console.log(user.name)
 * ```
 *
 * @template T - The type to parse into
 * @param dataType - Type name for error messages
 * @param constructorFunction - Object constructor function (returned by `dataObject()`)
 * @param guardFunction - Type guard function (returned by `dataGuard()`)
 * @param [doNotThrow=false] - If true, logs errors instead of throwing
 * @returns A function that parses unknown data into type T
 * @category Core Component
 */
export declare const dataParser: <T extends object>(dataType: string, constructorFunction: DataConstructor<T>, guardFunction: DataObjectGuard<T>, doNotThrow?: boolean) => DataConstructor<T>;

/**
 * Custom internal error class for data validation failures.
 *
 * Provides detailed error messages when data validation fails, including:
 * - The expected data type name
 * - The actual value that failed validation
 * - Optional details about which specific validation failed
 *
 * @example
 * ```typescript
 * throw new DataValidationError('UserData', invalidData, 'age must be a number')
 * ```
 *
 * @category Core Component
 */
export declare class DataValidationError extends Error {
    /** Name of the expected type */
    dataType: string;
    /** The value that failed validation */
    value: unknown;
    /** Optional details about the validation failure */
    detail?: string;
    constructor(
    /** Name of the expected type */
    dataType: string, 
    /** The value that failed validation */
    value: unknown, 
    /** Optional details about the validation failure */
    detail?: string);
}

/**
 * Complete object definition combining constructor, guard, and parser functions.
 * Provides a unified interface for working with typed data objects.
 * - Combined parts with {@link NamedConstructor}, {@link NamedGuard} and {@link NamedParser}
 *
 * @template Type - The object type being defined
 * @template TypeName - The name to use for generated functions
 * @category Core Implementation
 */
declare type DefinedObject<Type extends object, TypeName extends string> = NamedConstructor<Type, TypeName> & NamedGuard<Type, TypeName> & NamedParser<Type, TypeName>;

/**
 * Creates a complete suite of functions for working with typed data objects.
 * Combines object construction, validation, and parsing into a single definition.
 *
 * This function generates:
 * - A constructor function for creating objects with defaults
 * - A type guard function for validation
 * - A parser function for safely handling unknown data
 *
 * All functions are named based on the provided type name:
 * - Constructor: [typeName]
 * - Guard / Validation: is[typeName]
 * - Parser: parse[typeName]
 *
 * @example
 * ```typescript
 * import { defineObject } from 'ts-data-objects/core'
 * import { isStr, isNum } from 'ts-data-objects/common'
 *
 * type UserData = {
 *   name: string
 *   age: number
 *   verified?: boolean
 * }
 *
 * const {
 *   UserData,      // Constructor
 *   isUserData,    // Type guard
 *   parseUserData  // Parser
 * } = defineObject<UserData>('UserData', {
 *   defaultValues: { verified: false },
 *   predicate: o => (
 *     isStr(o?.name) &&
 *     isNum(o?.age)
 *   )
 * })
 *
 * // Usage:
 * const user = UserData({ name: 'John', age: 20 })
 *
 * if (isUserData(someData)) {
 *   // TypeScript now knows `someData` is now `UserData`
 *   console.log(someData)
 * }
 *
 * // if the apiData is correct according to UserData guard, the data is validated
 * try {
 *   const receivedUser = parseUserData(apiData)
 * }
 * catch (e: any) {
 *   // Handle the error...
 * }
 * ```
 *
 * @template Type - The object type to define
 * @template TypeName - The name to use for generated functions
 * @param typeName - Name used to generate function names
 * @param options - Configuration for the object definition, see {@link DefineObjectParams}
 * @returns Object containing named constructor, guard, and parser functions
 * @category Core Implementation
 */
export declare const defineObject: <Type extends object, TypeName extends string>(typeName: TypeName, options: DefineObjectParams<Type>) => DefinedObject<Type, TypeName>;

/**
 * Configuration parameters for creating a complete data object definition.
 *
 * @template T - The type of object being defined
 * @property [defaultValues] - Optional default values for object properties
 * @property predicate - Validation function for type checking
 * @property [doNotThrow] - Whether to suppress validation errors
 * @category Core Implementation
 */
declare type DefineObjectParams<T extends object> = {
    defaultValues?: T;
    predicate: GuardPredicate<T>;
    doNotThrow?: boolean;
};

/**
 * A semantic alias for TypeScript's `Partial<T>` utility type.
 * Makes code more readable by explicitly indicating expected partial input.
 *
 * @template T - The type to make partial
 * @category Common Utils
 */
declare type Expect<T> = Partial<T>;

/**
 * Type signature for predicate functions that validate JSON objects.
 * Used to check if a partial object matches expected type constraints.
 *
 * @template T - The object type to validate
 * @param [o] - Optional partial input data to validate
 * @returns Boolean indicating whether the input satisfies type constraints
 * @category Core Component
 */
declare type GuardPredicate<T extends object> = (o?: Expect<T>) => boolean;

/**
 * Checks if a value is an array where every element satisfies the provided predicate
 *
 * @example
 * ```typescript
 * import { isArrayOf, isStr } from 'ts-data-objects'
 *
 * if (isArrayOf(someValue, isStr)) {
 *   someValue.push('someValue is string array')
 * }
 * ```
 *
 * @template T The expected type of array elements
 * @param value - The value to check
 * @param predicate - The type guard function to apply to each array element
 * @returns A type predicate indicating whether the value is an array of type T
 * @category Assertions
 */
export declare const isArrayOf: <T>(value: unknown, predicate: Predicate<T>) => value is T[];

/**
 * Type guard function for boolean values.
 *
 * @example
 * ```typescript
 * isBool(true)       // returns true
 * isBool('true')     // returns false
 * isBool(0)          // returns false
 * isBool(null)       // returns false
 * isBool(undefined)  // returns false
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is a boolean
 * @category Assertions
 */
export declare const isBool: (value: unknown) => value is boolean;

/**
 * Type guard function for number values.
 *
 * @example
 * ```typescript
 * isNum(42)         // returns true
 * isNum('42')       // returns false
 * isNum(NaN)        // returns true - but will not occur in JSON data
 * isNum(null)       // returns false
 * isNum(undefined)  // returns false
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is a number
 * @category Assertions
 */
export declare const isNum: (value: unknown) => value is number;

/**
 * Checks if a value satisfies the provided simple object predicate
 * - Intended for user generated TS data objects residing inside other interfaces
 *
 * @template T The expected type of the object
 * @param value - The value to check
 * @param predicate - The type guard function to check if the value is of type T
 * @returns A type predicate indicating whether the value is null, undefined, or of type T
 * @category Assertions
 */
export declare const isObject: <T>(value: unknown, predicate: Predicate<T> | PredicateFunction) => value is T;

/**
 * Checks if a value is either null, undefined, or an array where every element satisfies the provided predicate
 *
 * @template T The expected type of array elements
 * @param value - The value to check
 * @param predicate - The type guard function to apply to each array element
 * @returns A type predicate indicating whether the value is null, undefined, or an array of type T
 * @category Assertions
 */
export declare const isOptionalArrayOf: <T>(value: unknown, predicate: Predicate<T>) => value is T[];

/**
 * Type guard function for optional boolean values
 *
 * @example
 * ```typescript
 * isBool(true)       // returns true
 * isBool('true')     // returns false
 * isBool(0)          // returns false
 * isBool(null)       // returns true
 * isBool(undefined)  // returns true
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is boolean or null/undefined
 * @category Assertions
 */
export declare const isOptionalBool: (value: unknown) => value is boolean;

/**
 * Type guard function for optional number values.
 *
 * @example
 * ```typescript
 * isNum(42)         // returns true
 * isNum('42')       // returns false
 * isNum(NaN)        // returns true
 * isNum(null)       // returns true
 * isNum(undefined)  // returns true
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is a number
 * @category Assertions
 */
export declare const isOptionalNum: (value: unknown) => value is number;

/**
 * Checks if a value is either null, undefined, or satisfies the provided simple object predicate
 * - Intended for user generated TS data objects residing inside other interfaces
 *
 * @template T The expected type of the object
 * @param value - The value to check
 * @param predicate - The type guard function to check if the value is of type T
 * @returns A type predicate indicating whether the value is null, undefined, or of type T
 * @category Assertions
 */
export declare const isOptionalObject: <T>(value: unknown, predicate: Predicate<T>) => value is T;

/**
 * Type guard function for string values.
 *
 * @example
 * ```typescript
 * isStr('hello')    // returns true
 * isStr(42)         // returns false
 * isStr('')         // returns true
 * isStr(null)       // returns true
 * isStr(undefined)  // returns true
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is a string
 * @category Assertions
 */
export declare const isOptionalStr: (value: unknown) => value is string;

/**
 * Type guard function for string values.
 *
 * @example
 * ```typescript
 * isStr('hello')    // returns true
 * isStr(42)         // returns false
 * isStr('')         // returns true
 * isStr(null)       // returns false
 * isStr(undefined)  // returns false
 * ```
 *
 * @param value - Any value to check
 * @returns Type predicate indicating if the value is a string
 * @category Assertions
 */
export declare const isStr: (value: unknown) => value is string;

/**
 * Creates a named constructor function type using the provided type name.
 * - Example: For name "User", creates { User: (data?) => UserType }
 * - Part of {@link DefinedObject}.
 * @category Core Implementation
 */
declare type NamedConstructor<Type extends object, TypeName extends string> = {
    [N in TypeName as `${N}`]: DataConstructor<Type>;
};

/**
 * Creates a named type guard function type with 'is' prefix.
 * - Example: For name "User", creates { isUser: (data?) => data is UserType }
 * - Part of {@link DefinedObject}.
 * @category Core Implementation
 */
declare type NamedGuard<Type extends object, TypeName extends string> = {
    [N in TypeName as `is${N}`]: DataObjectGuard<Type>;
};

/**
 * Creates a named parser function type with 'parse' prefix.
 * - Example: For name "User", creates { parseUser: (data?) => UserType }
 * - Part of {@link DefinedObject}.
 * @category Core Implementation
 */
declare type NamedParser<Type extends object, TypeName extends string> = {
    [N in TypeName as `parse${N}`]: DataConstructor<Type>;
};

/**
 * Type for a predicate function that performs a type guard check
 *
 * @template T The type being checked against
 * @param value - The unknown value to check
 * @returns A type predicate indicating whether the value is of type T
 * @category Assertions
 */
declare type Predicate<T> = (value: unknown) => value is T;

/**
 * A generic predicate function type that tests any value and returns a boolean.
 * - TS-wise inferior to {@link Predicate}, but is useful when writing custom predicate logic
 * inside one of functions
 *
 * @template T - The type of value being tested (inferred from usage)
 * @param value - The value to test
 * @returns A boolean indicating whether the value satisfies the predicate condition
 * @category Assertions
 */
declare type PredicateFunction = (value: any) => boolean;

export { }
