import type { evaluate, List, NumberLiteral, Thunk } from "../../../dev/utils/src/main.js" import type { IndexedPropInput, NonVariadicIndexMatcherSource, VariadicIndexMatcherSource } from "./indexed.js" import type { PropValueInput } from "./named.js" import type { NamedPropsInput, PropsInput, PropsInputTuple } from "./props.js" import type { inferTypeInput, TypeInput, TypeNode } from "./type.js" export type inferPropsInput = input extends PropsInputTuple ? inferIndexed> : input extends NamedPropsInput ? inferNamedProps : never type inferIndexed< indexed extends IndexedPropInput[], result = unknown > = indexed extends [ infer entry extends IndexedPropInput, ...infer tail extends IndexedPropInput[] ] ? inferIndexed< tail, entry["key"] extends { readonly regex: VariadicIndexMatcherSource } ? result extends List ? [...result, ...inferTypeInput[]] : never : entry["key"] extends { readonly regex: NonVariadicIndexMatcherSource } ? inferTypeInput[] : Record< Extract, PropertyKey>, inferTypeInput > > : result type inferNamedProps< named extends NamedPropsInput, indexed extends IndexedPropInput[] > = [named, indexed[0]["key"]] extends | [TupleLengthProps, unknown] | [unknown, { readonly regex: VariadicIndexMatcherSource }] ? inferNonVariadicTupleProps & inferObjectLiteralProps< Omit > : inferObjectLiteralProps type inferObjectLiteralProps = {} extends named ? unknown : evaluate< { [k in requiredKeyOf]: inferPropValue } & { [k in optionalKeyOf]?: inferPropValue } > type inferPropValue = value extends Thunk< infer ret > ? inferResolvedPropValue : inferResolvedPropValue type inferResolvedPropValue = value extends TypeNode ? t : inferTypeInput type stringifiedNumericKeyOf = `${Extract}` type inferNonVariadicTupleProps< named extends NamedPropsInput, result extends unknown[] = [] > = `${result["length"]}` extends stringifiedNumericKeyOf ? inferNonVariadicTupleProps< named, [...result, inferPropValue] > : result type TupleLengthProps = { readonly length: { readonly prerequisite: true readonly value: { readonly basis: readonly ["===", length] } } } type requiredKeyOf = Exclude< keyof input, optionalKeyOf > type optionalKeyOf = { [k in keyof input]: input[k]["optional"] extends true ? k : never }[keyof input]