type ValidSelector = string | number | symbol; export type EventMessage = { selector: Selector, args: Args, }; export type RequestMessage = { selector: Selector, args: Args, callback: (result: Result) => void, }; export type Message = void extends Result ? EventMessage : RequestMessage; // export type EventMessage = { // selector: Selector, // args: Args, // }; // // export type RequestMessage = { // selector: Selector, // args: Args, // callback: (result: Result) => void, // }; // // export type Message = // | EventMessage // | RequestMessage; // // type Messages1 = { // [K in keyof I]: (I[K] extends (...args: [...ContextArgs, ...infer P]) => infer Q // ? (void extends Q ? EventMessage : RequestMessage) // : never); // }; type Messages1 = { [K in keyof I]: (I[K] extends (...args: [...ContextArgs, ...infer P]) => infer Q ? Message : never); }; // type Proj1 = I[K]; // type Proj = Proj1; // export type Messages = Proj>; export type Messages = Messages1[keyof I]; export type Methods = { [S in M['selector']]: ( M extends RequestMessage ? (...args: [...ContextArgs, ...P]) => R : M extends EventMessage ? (... args: [...ContextArgs, ...P]) => void : never); }; // interface I { // m1(a: string, b: number): boolean; // m2(): void; // m3(n: number): void; // m4(x: [string, string]): { k: string, j: string }; // m5(a: string, b: string[]): number; // v: string; // w: number; // }; // // const a = { a(): string { console.log('in a'); return 'hi'; }, b(): void { console.log('in b'); } }; // type A = typeof a; // type A1 = Messages; // type A2 = Methods; // const b: A2 = a; // export function performRequest( // i: { [s in S]: (...args: [...ContextArgs, ...A]) => R }, // m: { selector: S, args: A, callback: (result: R) => void }, // ...ctxt: ContextArgs) // : R // { // const r = i[m.selector](...ctxt, ... m.args); // m.callback(r); // return r; // } // export function performEvent( // i: { [s in S]: (...args: [...ContextArgs, ...A]) => void }, // m: { selector: S, args: A }, // ...ctxt: ContextArgs) // : void // { // i[m.selector](...ctxt, ...m.args); // } // function send( // i: { [s in S]: (...args: A) => R }, // m: { selector: S, args: A, callback?: (result: R) => void }) // : R; // function send( // i: { [s in S]: (...args: A) => void }, // m: { selector: S, args: A }) // : void; // function send( // i: { [s in S]: (...args: A) => R }, // m: { selector: S, args: A, callback?: (result: R) => void }) // : R // // function send>(i: I, m: M): [M, I] extends [RequestMessage, Methods] ? R : void // { // const r = i[m.selector](... m.args); // m.callback?.(r); // return r; // } export function perform, S extends ValidSelector, M extends RequestMessage, ContextArgs extends any[] = []>(i: I, m: M, ...ctxt: ContextArgs) : [M, I] extends [RequestMessage, Methods] ? R : void; export function perform, S extends ValidSelector, M extends EventMessage, ContextArgs extends any[] = []>(i: I, m: M, ...ctxt: ContextArgs): void; export function perform, S extends ValidSelector, M extends RequestMessage, R, ContextArgs extends any[] = []>(i: I, m: M, ...ctxt: ContextArgs): R { const r = i[m.selector](...ctxt, ... m.args); m.callback?.(r); return r; } // function perform, S extends ValidSelector, M extends RequestMessage>(i: I, m: M) // : [M, I] extends [RequestMessage, Methods] ? R : void; // function perform, S extends ValidSelector, M extends EventMessage>(i: I, m: M): void; // function perform, S extends ValidSelector, M extends RequestMessage>(i: I, m: M): R // { // const r = i[m.selector](... m.args); // m.callback?.(r); // return r; // } // const aa = perform(a, { selector: 'a', args: [], callback: (_r: string) => {} }); // const bb = perform(a, { selector: 'b', args: [], callback: (_r: void) => { console.log('bb'); } }); // const bb2 = perform(a, { selector: 'b', args: [] }); // // perform({ a(): string { return 'hi' } }, { selector: 'a', args: [123], callback: (_r: string) => {} }); // type Q = Messages; // type M = Methods; // type N = M; // type R = Messages>; // type S = R; // const x: Q = { selector: 'm2', args: [] };