{"version":3,"file":"optional.mjs","sources":["../../src/record/optional.mts"],"sourcesContent":["import { type StrictOmit } from 'ts-type-forge';\nimport { type AnyType, type Type } from '../type.mjs';\n\n/**\n * Converts a Type to an optional property type.\n *\n * @template T - The Type to make optional\n * @param t - The Type to make optional\n * @param options - Optional configuration\n * @param options.forceUndefinedDefault - If true, forces defaultValue to be undefined.\n *                                        Use this for recursive types to avoid infinite loops.\n *\n * @returns An OptionalPropertyType that can be used in record definitions\n *\n * @example\n * ```ts\n * import * as t from 'ts-fortress';\n *\n * type EvenNumber = Readonly<{ type: 'even'; next?: OddNumber }>;\n *\n * type OddNumber = Readonly<{ type: 'odd'; next?: EvenNumber }>;\n *\n * // When using optional fields in mutually recursive types,\n * // use forceUndefinedDefault to avoid infinite loops when accessing defaultValue\n * const EvenNumber: t.Type<EvenNumber> = t.recursion('EvenNumber', () =>\n *   t.record({\n *     type: t.literal('even'),\n *     next: t.optional(OddNumber, { forceUndefinedDefault: true }),\n *   }),\n * );\n *\n * const OddNumber: t.Type<OddNumber> = t.recursion('OddNumber', () =>\n *   t.record({\n *     type: t.literal('odd'),\n *     next: t.optional(EvenNumber, { forceUndefinedDefault: true }),\n *   }),\n * );\n * ```\n */\nexport const optional = <T extends AnyType>(\n  t: T,\n  options?: Partial<\n    Readonly<{\n      /**\n       * If true, forces defaultValue to be undefined.\n       * Use this for recursive types to avoid infinite loops.\n       * @default false\n       */\n      forceUndefinedDefault: boolean;\n    }>\n  >,\n): OptionalPropertyType<T> =>\n  // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n  ({\n    assertIs: t.assertIs,\n    is: t.is,\n    cast: t.cast,\n    fill: t.fill,\n    prune: t.prune,\n    validate: t.validate,\n    typeName: t.typeName,\n\n    defaultValue:\n      options?.forceUndefinedDefault === true\n        ? // For recursive types: set defaultValue to undefined to avoid infinite loops\n          undefined\n        : // For normal types: preserve the original defaultValue\n          t.defaultValue,\n\n    optional: true,\n  }) satisfies OptionalPropertyType<Type<unknown>> as OptionalPropertyType<T>;\n\nexport type OptionalPropertyType<T extends AnyType> = T &\n  Readonly<{ optional: true }>;\n\nexport type RequiredPropertyType<T extends AnyType> =\n  T extends OptionalPropertyType<T> ? StrictOmit<T, 'optional'> : T;\n\nexport const isOptionalProperty = <T extends AnyType>(\n  t: T,\n): t is OptionalPropertyType<T> => t.optional === true;\n"],"names":[],"mappings":"AAuCO,MAAM,QAAA,GAAW,CACtB,CAAA,EACA,OAAA;AAAA;AAAA,EAYC;AAAA,IACC,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,UAAU,CAAA,CAAE,QAAA;AAAA,IAEZ,YAAA,EACE,SAAS,qBAAA,KAA0B,IAAA;AAAA;AAAA,MAE/B;AAAA;AAAA;AAAA,MAEA,CAAA,CAAE;AAAA,KAAA;AAAA,IAER,QAAA,EAAU;AAAA;AACZ;AAQK,MAAM,kBAAA,GAAqB,CAChC,CAAA,KACiC,CAAA,CAAE,QAAA,KAAa;;;;"}