import { PrimitiveMap } from '../_types';
import { AnyFieldDescriptor, ArrayDtoFieldDescriptor, ArrayFieldDescriptor, BooleanFieldDescriptor, CustomFieldDescriptor, DateFieldDescriptor, DtoFieldDescriptor, EnumFieldDescriptor, IntegerFieldDescriptor, NumberFieldDescriptor, RegexFieldDescriptor, SchemaMap, StringFieldDescriptor } from './field-descriptor.type';
import { DtoDefinition } from './dto-definition.type';
type FieldOutputType<F extends AnyFieldDescriptor> = F extends StringFieldDescriptor ? string : F extends NumberFieldDescriptor ? number : F extends IntegerFieldDescriptor ? number : F extends BooleanFieldDescriptor ? boolean : F extends DateFieldDescriptor ? Date : F extends RegexFieldDescriptor ? string : F extends EnumFieldDescriptor<infer E> ? E : F extends ArrayFieldDescriptor<infer K> ? PrimitiveMap[K][] : F extends DtoFieldDescriptor<infer S> ? InferDto<DtoDefinition<S>> : F extends ArrayDtoFieldDescriptor<infer S> ? Array<InferDto<DtoDefinition<S>>> : F extends CustomFieldDescriptor<infer T> ? T : unknown;
type WithNullable<F extends AnyFieldDescriptor, T> = F extends {
    options: {
        isNullable: true;
    };
} ? T | null : T;
type InferFieldType<F extends AnyFieldDescriptor> = WithNullable<F, FieldOutputType<F>>;
type RequiredKeys<S extends SchemaMap> = {
    [K in keyof S]: S[K] extends {
        options: {
            isOptional: true;
        };
    } ? never : K;
}[keyof S];
type OptionalKeys<S extends SchemaMap> = {
    [K in keyof S]: S[K] extends {
        options: {
            isOptional: true;
        };
    } ? K : never;
}[keyof S];
/**
 * Derives the full TypeScript type from a DtoDefinition.
 *
 * - Required fields become required properties.
 * - `isOptional: true` fields become optional (`T | undefined`).
 * - `isNullable: true` fields become nullable (`T | null`).
 *
 * @example
 * const PersonDto = defineDto({ name: field.string(), age: field.integer() });
 * type PersonDto = InferDto<typeof PersonDto>;
 * // → { name: string; age: number }
 */
export type InferDto<D extends DtoDefinition> = D extends DtoDefinition<infer S> ? {
    [K in RequiredKeys<S>]: InferFieldType<S[K]>;
} & {
    [K in OptionalKeys<S>]?: InferFieldType<S[K]>;
} : never;
export {};
