{"version":3,"file":"valueof.mjs","sources":["../../src/record/valueof.mts"],"sourcesContent":["import { Arr, expectType } from 'ts-data-forge';\nimport { type IsNever, type UnknownRecord, type ValueOf } from 'ts-type-forge';\nimport { union } from '../compose/index.mjs';\nimport { undefinedType } from '../primitives/index.mjs';\nimport {\n  flattenShapeStructure,\n  hasRecordInternals,\n  type Type,\n  type TypeOf,\n} from '../type.mjs';\n\nexport type { ValueOf } from 'ts-type-forge';\n\nexport const valueof = <const R extends UnknownRecord>(\n  recordType: Type<R>,\n  options?: Partial<\n    Readonly<{\n      typeName: string;\n    }>\n  >,\n): ValueOfType<R> => {\n  if (!hasRecordInternals(recordType)) {\n    throw new Error(\n      `Expected a record type but received: ${recordType.typeName}`,\n    );\n  }\n\n  const shape = flattenShapeStructure(recordType.shapeStructure);\n\n  if (shape === undefined) {\n    throw new Error(\n      `valueof() requires a simple or intersection record type, but received a union type`,\n    );\n  }\n\n  const types = Object.values(shape);\n\n  if (Arr.isMinLengthTuple(types, 2)) {\n    return union(types, {\n      typeName: options?.typeName ?? `ValueOf<${recordType.typeName}>`,\n    });\n  }\n\n  if (Arr.isNonEmpty(types)) {\n    return types[0];\n  }\n\n  // types is empty\n\n  // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n  return undefinedType satisfies Type<undefined> as ValueOfType<R>;\n};\n\ntype ValueOfType<T extends UnknownRecord> =\n  IsNever<keyof T> extends true ? Type<undefined> : Type<ValueOf<T>>;\n\n// --- expectType assertions ---\n\n{\n  // valueof extracts union of value types\n  type Base = Readonly<{ a: 0; b: 1; c: 2 }>;\n\n  expectType<TypeOf<ReturnType<typeof valueof<Base>>>, 0 | 1 | 2>('=');\n\n  // valueof of single-key record yields that value type\n  type Single = Readonly<{ x: 'hello' }>;\n\n  expectType<TypeOf<ReturnType<typeof valueof<Single>>>, 'hello'>('=');\n\n  // valueof of empty record yields undefined\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n  type EmptyRecord = Readonly<{}>;\n\n  expectType<ValueOfType<EmptyRecord>, Type<undefined>>('=');\n\n  expectType<TypeOf<ReturnType<typeof valueof<EmptyRecord>>>, undefined>('=');\n}\n"],"names":[],"mappings":";;;;;;;MAaa,OAAA,GAAU,CACrB,UAAA,EACA,OAAA,KAKmB;AACnB,EAAA,IAAI,CAAC,kBAAA,CAAmB,UAAU,CAAA,EAAG;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,qCAAA,EAAwC,WAAW,QAAQ,CAAA;AAAA,KAC7D;AAAA,EAAA;AAGF,EAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,UAAA,CAAW,cAAc,CAAA;AAE7D,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kFAAA;AAAA,KACF;AAAA,EAAA;AAGF,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AAEjC,EAAA,IAAI,GAAA,CAAI,gBAAA,CAAiB,KAAA,EAAO,CAAC,CAAA,EAAG;AAClC,IAAA,OAAO,MAAM,KAAA,EAAO;AAAA,MAClB,QAAA,EAAU,OAAA,EAAS,QAAA,IAAY,CAAA,QAAA,EAAW,WAAW,QAAQ,CAAA,CAAA;AAAA,KAC9D,CAAA;AAAA,EAAA;AAGH,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,MAAM,CAAC,CAAA;AAAA,EAAA;AAMhB,EAAA,OAAO,aAAA;AACT;;;;"}