144 lines
5.6 KiB
TypeScript
144 lines
5.6 KiB
TypeScript
|
type ValidSelector = string | number | symbol;
|
||
|
|
||
|
export type EventMessage<Selector extends ValidSelector, Args extends any[]> = {
|
||
|
selector: Selector,
|
||
|
args: Args,
|
||
|
};
|
||
|
|
||
|
export type RequestMessage<Selector extends ValidSelector, Args extends any[], Result> = {
|
||
|
selector: Selector,
|
||
|
args: Args,
|
||
|
callback: (result: Result) => void,
|
||
|
};
|
||
|
|
||
|
export type Message<Selector extends ValidSelector, Args extends any[], Result> =
|
||
|
void extends Result ? EventMessage<Selector, Args> : RequestMessage<Selector, Args, Result>;
|
||
|
|
||
|
// export type EventMessage<Selector extends ValidSelector, Args extends any[]> = {
|
||
|
// selector: Selector,
|
||
|
// args: Args,
|
||
|
// };
|
||
|
//
|
||
|
// export type RequestMessage<Selector extends ValidSelector, Args extends any[], Result> = {
|
||
|
// selector: Selector,
|
||
|
// args: Args,
|
||
|
// callback: (result: Result) => void,
|
||
|
// };
|
||
|
//
|
||
|
// export type Message<Selector extends ValidSelector, Args extends any[], Result> =
|
||
|
// | EventMessage<Selector, Args>
|
||
|
// | RequestMessage<Selector, Args, Result>;
|
||
|
//
|
||
|
// type Messages1<I, ContextArgs extends any[]> = {
|
||
|
// [K in keyof I]: (I[K] extends (...args: [...ContextArgs, ...infer P]) => infer Q
|
||
|
// ? (void extends Q ? EventMessage<K, P> : RequestMessage<K, P, Q>)
|
||
|
// : never);
|
||
|
// };
|
||
|
|
||
|
type Messages1<I, ContextArgs extends any[]> = {
|
||
|
[K in keyof I]: (I[K] extends (...args: [...ContextArgs, ...infer P]) => infer Q
|
||
|
? Message<K, P, Q>
|
||
|
: never);
|
||
|
};
|
||
|
|
||
|
// type Proj1<I, K extends keyof I> = I[K];
|
||
|
// type Proj<I> = Proj1<I, keyof I>;
|
||
|
// export type Messages<I, ContextArgs extends any[] = []> = Proj<Messages1<I, ContextArgs>>;
|
||
|
|
||
|
export type Messages<I, ContextArgs extends any[] = []> = Messages1<I, ContextArgs>[keyof I];
|
||
|
|
||
|
export type Methods<M extends { selector: ValidSelector }, ContextArgs extends any[] = []> = {
|
||
|
[S in M['selector']]: (
|
||
|
M extends RequestMessage<S, infer P, infer R> ? (...args: [...ContextArgs, ...P]) => R :
|
||
|
M extends EventMessage<S, infer P> ? (... 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<A>;
|
||
|
// type A2 = Methods<A1>;
|
||
|
// const b: A2 = a;
|
||
|
|
||
|
// export function performRequest<S extends ValidSelector, A extends any[], R, ContextArgs extends any[] = []>(
|
||
|
// 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<S extends ValidSelector, A extends any[], ContextArgs extends any[] = []>(
|
||
|
// i: { [s in S]: (...args: [...ContextArgs, ...A]) => void },
|
||
|
// m: { selector: S, args: A },
|
||
|
// ...ctxt: ContextArgs)
|
||
|
// : void
|
||
|
// {
|
||
|
// i[m.selector](...ctxt, ...m.args);
|
||
|
// }
|
||
|
|
||
|
// function send<S extends ValidSelector, A extends any[], R>(
|
||
|
// i: { [s in S]: (...args: A) => R },
|
||
|
// m: { selector: S, args: A, callback?: (result: R) => void })
|
||
|
// : R;
|
||
|
// function send<S extends ValidSelector, A extends any[], R>(
|
||
|
// i: { [s in S]: (...args: A) => void },
|
||
|
// m: { selector: S, args: A })
|
||
|
// : void;
|
||
|
// function send<S extends ValidSelector, A extends any[], R>(
|
||
|
// i: { [s in S]: (...args: A) => R },
|
||
|
// m: { selector: S, args: A, callback?: (result: R) => void })
|
||
|
// : R
|
||
|
// // function send<I extends {}, M extends Messages<I>>(i: I, m: M): [M, I] extends [RequestMessage<any, any, infer R>, Methods<M>] ? R : void
|
||
|
// {
|
||
|
// const r = i[m.selector](... m.args);
|
||
|
// m.callback?.(r);
|
||
|
// return r;
|
||
|
// }
|
||
|
|
||
|
export function perform<I extends Methods<M, ContextArgs>, S extends ValidSelector, M extends RequestMessage<S, any, any>, ContextArgs extends any[] = []>(i: I, m: M, ...ctxt: ContextArgs)
|
||
|
: [M, I] extends [RequestMessage<S, any, infer R>, Methods<M>] ? R : void;
|
||
|
export function perform<I extends Methods<M, ContextArgs>, S extends ValidSelector, M extends EventMessage<S, any>, ContextArgs extends any[] = []>(i: I, m: M, ...ctxt: ContextArgs): void;
|
||
|
export function perform<I extends Methods<M, ContextArgs>, S extends ValidSelector, M extends RequestMessage<S, any, any>, 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<I extends Methods<M>, S extends ValidSelector, M extends RequestMessage<S, any, any>>(i: I, m: M)
|
||
|
// : [M, I] extends [RequestMessage<S, any, infer R>, Methods<M>] ? R : void;
|
||
|
// function perform<I extends Methods<M>, S extends ValidSelector, M extends EventMessage<S, any>>(i: I, m: M): void;
|
||
|
// function perform<I extends Methods<M>, S extends ValidSelector, M extends RequestMessage<S, any, any>>(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<I>;
|
||
|
// type M = Methods<Q>;
|
||
|
// type N = M;
|
||
|
// type R = Messages<Methods<Q>>;
|
||
|
// type S = R;
|
||
|
|
||
|
// const x: Q = { selector: 'm2', args: [] };
|