import type {Intersection} from 'tslang'; import * as x from 'x-value'; declare global { namespace Backit { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface BackStates { // namespace: { // stateName: [...StateWriteArgs]; // }; // namespace: typeof demoBackStates; } type BackStatesDefinition = Intersection; } } export type BackStatesInReturn = { [TKey in keyof Backit.BackStatesDefinition]?: Backit.BackStatesDefinition[TKey] extends infer TInput extends x.TypeInMediumsPartial ? x.MediumTypeOf : never; } extends infer TBackStates ? { states?: TBackStates | TBackStates[]; } : never; export type BackStatesDefinition = Record>; const backStatesDefinitions: BackStatesDefinition[] = []; export type GeneralXBackStatesInReturn = x.XTypeOfValue<{ states?: object | object[]; }>; let BackStatesInReturn: GeneralXBackStatesInReturn | undefined; export function getXBackStatesInReturn(): GeneralXBackStatesInReturn { if (!BackStatesInReturn) { const BackStates = x.object( Object.fromEntries( backStatesDefinitions.flatMap(definition => Object.entries(definition).map(([key, Input]) => [ key, Input.optional(), ]), ), ), ); BackStatesInReturn = x.object({ states: x.union([x.array(BackStates), BackStates]).optional(), }); } return BackStatesInReturn; } export function extendBackStates( backStates: Backit.BackStates[keyof Backit.BackStates], ): void { if (BackStatesInReturn) { throw new Error( 'Cannot extend back states after `getXBackStates` being called.', ); } backStatesDefinitions.push(backStates); }