export type Err<error> = {
    kind: "Err";
    error: error;
};
export type Ok<value> = {
    kind: "Ok";
    value: value;
};
export type Result<value> = Ok<value> | Err<string>;
export declare function Ok<const value>(value: value): Result<value>;
export declare function Err<const value>(error: string): Result<value>;
declare const OneOf: unique symbol;
type OneOf<x extends readonly string[]> = typeof OneOf;
declare const VariableList: unique symbol;
type VariableList<x extends FlagArgument<VariableListBasicTypes>> = typeof VariableList;
declare const List: unique symbol;
type List<x extends readonly FlagArgument<BasicTypes>[]> = typeof List;
export type BasicTypes = string | number | boolean;
export type VariableListBasicTypes = BasicTypes | OneOf<readonly string[]>;
export type BaseParseableTypes = BasicTypes | OneOf<readonly string[]> | VariableList<BaseVariableListFlagArgument<VariableListBasicTypes>> | List<readonly BaseFlagArgument<BasicTypes>[]>;
export type KnownTypes = BaseParseableTypes;
export type BaseVariableListFlagArgument<flagType extends VariableListBasicTypes> = flagType extends BasicTypes ? BaseFlagArgument<flagType> : flagType extends OneOf<readonly string[]> ? OneOfArgument<readonly string[]> : never;
export type BaseFlagArgument<flagType extends BasicTypes> = flagType extends string ? StringArgument<string> : flagType extends number ? NumberArgument<number> : flagType extends boolean ? BooleanArgument<boolean> : never;
export type FlagArgument<flagType extends BaseParseableTypes> = flagType extends BasicTypes ? BaseFlagArgument<flagType> : flagType extends OneOf<infer inner> ? OneOfArgument<inner> : flagType extends VariableList<infer inner> ? VariableListArgument<inner> : flagType extends List<infer inner> ? ListArgument<inner> : never;
type InferVariableListFlagType<flagArgument extends VariableListArgument<FlagArgument<VariableListBasicTypes>>> = flagArgument extends VariableListArgument<infer inner> ? inner extends StringArgument<string> ? string[] : inner extends NumberArgument<number> ? number[] : inner extends BooleanArgument<boolean> ? boolean[] : inner extends OneOfArgument<infer union> ? readonly union[number][] : "never" : never;
type InferListFlagTypeRecursive<inner extends readonly FlagArgument<BasicTypes>[]> = inner extends readonly [infer first, ...infer rest] ? first extends StringArgument<string> ? rest extends readonly FlagArgument<BasicTypes>[] ? [string, ...InferListFlagTypeRecursive<rest>] : [string] : first extends NumberArgument<number> ? rest extends readonly FlagArgument<BasicTypes>[] ? [number, ...InferListFlagTypeRecursive<rest>] : [number] : first extends BooleanArgument<boolean> ? rest extends readonly FlagArgument<BasicTypes>[] ? [boolean, ...InferListFlagTypeRecursive<rest>] : [boolean] : [] : inner extends StringArgument<string> ? [string] : inner extends NumberArgument<number> ? [number] : inner extends BooleanArgument<boolean> ? [boolean] : [];
type InferListFlagType<flagArgument extends ListArgument<readonly FlagArgument<BasicTypes>[]>> = flagArgument extends ListArgument<infer inner> ? InferListFlagTypeRecursive<inner> : never;
type InferOneOfFlagType<flagArgument extends OneOfArgument<readonly string[]>> = flagArgument extends OneOfArgument<infer inner> ? inner extends readonly string[] ? inner[number] : inner : never;
export type InferFlagArgumentType<flagArgument extends FlagArgument<KnownTypes>> = flagArgument extends StringArgument<string> ? string : flagArgument extends NumberArgument<number> ? number : flagArgument extends BooleanArgument<boolean> ? boolean : flagArgument extends OneOfArgument<infer inner> ? InferOneOfFlagType<flagArgument> : flagArgument extends VariableListArgument<infer inner> ? InferVariableListFlagType<flagArgument> : flagArgument extends ListArgument<readonly FlagArgument<BasicTypes>[]> ? InferListFlagType<flagArgument> : never;
/**
 * A result from a flag: contains the flag name, if it was present in the arguments,
 * and whether the arguments were parsed as described.
 */
export type FlagResult<flagArgument extends FlagArgument<KnownTypes>, name extends string> = {
    flag: Flag<flagArgument, name>;
    isPresent: boolean;
    arguments: Result<InferFlagArgumentType<flagArgument>>;
};
export type StringArgument<encode extends string> = {
    kind: "StringArgument";
};
/**
 * An argument parser that treats an argument as a string
 */
export declare function string(): FlagArgument<string>;
export type NumberArgument<encode extends number> = {
    kind: "NumberArgument";
};
/**
 * An argument parser that treats an argument as a number
 */
export declare function number(): NumberArgument<number>;
export type BooleanArgument<encode extends boolean> = {
    kind: "BooleanArgument";
};
/**
 * An argument parser that treats an argument as a boolean
 */
export declare function boolean(): BooleanArgument<boolean>;
/**
 * An argument parser that always passes
 */
export declare function empty(): FlagArgument<true>;
export type ListArgument<flagTypes extends readonly FlagArgument<BasicTypes>[]> = {
    kind: "ListArgument";
    items: flagTypes;
};
/**
 * An argument parser that treats an argument as a list
 */
export declare function list<const flagTypes extends readonly FlagArgument<BasicTypes>[]>(flagArgumentParsers: flagTypes): ListArgument<flagTypes>;
export type VariableListArgument<flagType extends FlagArgument<VariableListBasicTypes>> = {
    kind: "VariableListArgument";
    item: flagType;
};
/**
 * An argument parser that treats an argument as a list
 */
export declare function variableList<flagType extends FlagArgument<VariableListBasicTypes>>(flagArgumentParser: flagType): VariableListArgument<flagType>;
export type OneOfArgument<encode extends readonly string[]> = {
    kind: "OneOfArgument";
    items: encode;
};
/**
 * An argument parser that treats an argument as an enum
 */
export declare function oneOf<const encode extends readonly string[]>(items: encode): OneOfArgument<encode>;
export type Short<flagArgument extends FlagArgument<KnownTypes>, name extends string> = {
    kind: "Short";
    name: name;
    help: string;
    parser: flagArgument;
};
export type Long<flagArgument extends FlagArgument<KnownTypes>, name extends string> = {
    kind: "Long";
    name: name;
    help: string;
    parser: flagArgument;
};
export type Both<flagArgument extends FlagArgument<KnownTypes>, name extends string> = {
    kind: "Both";
    shortName: string;
    longName: name;
    help: string;
    parser: flagArgument;
};
export type Flag<flagType extends FlagArgument<KnownTypes>, name extends string> = Short<flagType, name> | Long<flagType, name> | Both<flagType, name>;
/**
 * A short flag, like -y
 */
export declare function shortFlag<const flagArgument extends FlagArgument<KnownTypes>, const name extends string>(name: name, help: string, parser: flagArgument): Short<flagArgument, name>;
/**
 * A long flag, like --yes
 */
export declare function longFlag<const flagArgument extends FlagArgument<KnownTypes>, const name extends string>(name: name, help: string, parser: flagArgument): Long<flagArgument, name>;
/**
 * A short or long flag, like -y or --yes
 */
export declare function bothFlag<const flagArgument extends FlagArgument<KnownTypes>, const name extends string>(shortName: string, longName: name, help: string, parser: flagArgument): Both<flagArgument, name>;
export type InferFlagType<x extends Flag<FlagArgument<BaseParseableTypes>, string>> = x extends Flag<FlagArgument<infer flagType>, infer name> ? flagType : never;
export type InferFlagName<x extends Flag<FlagArgument<BaseParseableTypes>, string>> = x extends Flag<infer flagType, infer name> ? name : never;
export type InferFlagResultType<x extends FlagResult<FlagArgument<KnownTypes>, string>> = x extends FlagResult<infer flagArgument, infer name> ? InferFlagArgumentType<flagArgument> : never;
export type ProgramParser<flagTypes extends readonly Flag<FlagArgument<KnownTypes>, string>[]> = {
    flags: {
        [k in flagTypes[number] as InferFlagName<k>]: k;
    };
};
/**
 * A Program contains all arguments given to it, and an record of all the flags
 */
export type Program<flagTypes extends readonly Flag<FlagArgument<KnownTypes>, string>[]> = {
    args: readonly string[];
    readonly flags: {
        [k in flagTypes[number] as InferFlagName<k>]: FlagResult<k["parser"], InferFlagName<k>>;
    };
};
/**
 * Extracted values from a parsed program
 */
export type ProgramValues<flags extends readonly Flag<FlagArgument<KnownTypes>, string>[]> = {
    [k in flags[number] as InferFlagName<k>]: InferFlagArgumentType<k["parser"]> | undefined;
};
/**
 * Infer a Program from a given parser, e.g:
 * ```
 * function handleFlag(program: ProgramOf<typeof parser>) {}
 * ```
 */
export type ProgramOf<parser extends ProgramParser<readonly Flag<FlagArgument<KnownTypes>, string>[]>> = parser extends ProgramParser<infer flags> ? Program<flags> : never;
/**
 * Infer a ProgramValues from a given parser, e.g:
 * ```
 * function handleFlag(yes: ProgramValuesOf<typeof parser>["yes"]) {}
 * ```
 */
export type ProgramValuesOf<parser extends ProgramParser<readonly Flag<FlagArgument<KnownTypes>, string>[]>> = parser extends ProgramParser<infer flags> ? ProgramValues<flags> : never;
export {};
