import { Binding } from "../data/Binding"; import { isString } from "../util/isString"; import { AccessorChain } from "../data/createAccessorModelProxy"; import { Selector } from "../data/Selector"; import { Expr } from "./Prop"; // Helper type to infer value type from AccessorChain, handling `any` correctly type InferAccessorValue = 0 extends 1 & T ? any : T extends AccessorChain ? V : never; export function expr(code: string): Expr; export function expr(arg1: AccessorChain, compute: (v1: V1) => R): Selector; export function expr( arg1: AccessorChain, arg2: AccessorChain, compute: (v1: V1, v2: V2) => R, ): Selector; export function expr( arg1: AccessorChain, arg2: AccessorChain, arg3: AccessorChain, compute: (v1: V1, v2: V2, v3: V3) => R, ): Selector; export function expr( arg1: AccessorChain, arg2: AccessorChain, arg3: AccessorChain, arg4: AccessorChain, compute: (v1: V1, v2: V2, v3: V3, v4: V4) => R, ): Selector; export function expr[], R>( ...args: [...accessors: T, compute: (...values: { [K in keyof T]: InferAccessorValue }) => R] ): Selector; export function expr(...args: any[]): any { let text = args[0]; if (isString(text)) return { expr: text, }; let getters: any[] = []; let compute = args[args.length - 1]; for (let i = 0; i < args.length - 1; i++) getters.push(Binding.get(args[i]).value); return (data: any) => { let argv = getters.map((g) => g(data)); return compute.apply(null, argv); }; }