/**
    * Which type the random.array operation would return (so it wouldn't return unknown)
    */
    type ArrayType<T> = T extends 'number' ? number[]
        : T extends 'string' ? string[]
        : T extends 'boolean' ? boolean[]
        : T extends 'date' ? Date[]
        : T extends 'bigint' ? bigint[]
        : T extends 'symbol' ? symbol[]
        : T extends 'unknown' ? unknown[]
        : never;

/**
 * A list of all avaliable primitive types that are supported by the library
 */
type PrimitiveTypeStrings =
    'number' | 'string' | 'boolean' | 'symbol' | 'date' | 'bigint'| 'unknown';

/**
 * Extra options for the random string options
 */
declare const random: {
    /**
     * Generate a random number between min and max
     * @param {number} min the minimum number to generate
     * @param {number} max the maximum number to generate
     * @returns {number} a random number between min and max
     * @see random.bigint for a bigint version
     * @example
     * random.number(0, 100) // 50
     * random.number(0.5, 1.5) // 1.2
     */
    number: (min: number, max: number) => number;
    /**
     * Generate a random string
     * @param {number} length the length of the string
     * @param {string} characters the characters to generate the string from (default: allCharacters)
     * @returns {string} a random string
     * @example
     * random.string(10) // 'aBcDeFgHiJ'
     * random.string(10, {includeUpperCase: false}) // 'abcdefghij'
    */
    string: (length: number, characters?: string) => string;
    /**
     * @returns {string} a random character
     * @example
     * random.char(); //returns 'A'
     * random.char(); //returns 'b'
     */
    char: () => string;
    /**
     * Generate a random boolean
     * @returns {boolean} a random boolean
     * @example
     * random.boolean() // true
     * random.boolean() // false
     */
    boolean: () => boolean;
    /**
     * Generates a random date between minDate and maxDate
     * @param {Date} minData optional minimum date
     * @param {Date maxDate optional maximum date
     * @returns {Date} a random date
     *
     * @example
     * random.date() // 2021-08-01T12:00:00.000Z
     * random.date(new Date('2021-08-01T12:00:00.000Z'), new Date('2021-08-01T12:00:00.000Z')) // 2021-08-01T12:00:00.000Z
     */
    date: (minData?: Date | string, maxDate?: Date | string) => Date;
    /**
     *
     * @returns {symbol} a random symbol
     * @example
     * random.symbol() // Symbol(5)
     * random.symbol() // Symbol(10)
     */
    symbol: () => symbol;
    /**
     * Generates a random bigint
     * @param {bigint} min minimum number
     * @param {bigint} max maximum number
     * @returns {bigint} a random bigint
     * @see random.number for a number version
     * @example
     * random.bigint(0n, 100n) // 50n
     * random.bigint(0n, 100n) // 10n
     */
    bigint: (min: bigint, max: bigint) => bigint;
    /**
     * Generate a random array
     *
     * Can generate an array of numbers, strings, booleans, symbols, dates and bigints
     * @param {number} length the length of the array
     * @param {T} type (random by default) the type of the array
     * @returns {T[]} a random array
     * @example
     * random.array(10, 'number') // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
     * random.array(10, 'string') // [ 'aBcDeFgHiJ', 'tUvWxYzAbC', 'dEfGhIjKlM', 'nOpQrStUvW', 'xYzAbCdEfG', 'hIjKlMnOpQ', 'rStUvWxYzA', 'bCdEfGhIjK', 'lMnOpQrStU', 'vWxYzAbCdE' ]
     * random.array(10, 'boolean') // [ true, false, true, false, true, false, true, false, true, false ]
     * random.array(10, 'symbol') // [ Symbol
    */
    array: <T extends PrimitiveTypeStrings>(length: number, type?: T) => ArrayType<T>;
    /**
     * Get a random element from an array
     * @param {T[]} array the array to get the element from
     * @returns {T} A random element from the array
     */
    elementFromArray: <T_1>(array: T_1[]) => T_1 | undefined;
    /**
     * Get a random key from an object
     * @param {T extends object} object
     * @returns {keyof T} a random key from the object
     */
    keyFromObject: <T_2 extends object>(object: T_2) => keyof T_2;
    /**
     * Gets a random value from an object
     * @param {T} object the object that the value would be taken from
     * @returns {T[keyof T]} random value from the object
     */
    valueFromObject: <T_3 extends object>(object: T_3) => T_3[keyof T_3];
    /**
     * `Still experimental`
     *
     * Generates a random object based on the object passed
     *
     * Important to note that the symbol type is not supported at the moment
     * @param {T} object a object to generate a random object from
     * @returns {T} a random object of the same type as the object passed
     * @example
     * random.object({a: 1, b: 'hello', c: {}}) // { a: 50, b: 'aBcDeFgHiJ', c: {} }
     *
     */
    object: <T_4 extends object>(object: T_4) => T_4;
};

export { random as default, random };
