Skip to content

Commit

Permalink
[TS] improved types to inherit Observable
Browse files Browse the repository at this point in the history
  • Loading branch information
kosich committed Oct 10, 2020
1 parent 5bddaa9 commit fde934f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
23 changes: 13 additions & 10 deletions src/proxify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,20 @@ export function proxify<O>(o: Observable<O>): Proxify<O> {
export type Proxify<O> =
// O is function ?
O extends (...args: any[]) => infer R
? // make it callable
(
...args: Parameters<O>
) => Proxify<R> & ProxiedPipeObservable<O> & Proxy<O>
: // simple proxy otherwise
ProxiedPipeObservable<O> & Proxy<O>;
? Proxy <O> & ICallableProxiedObservable<O, R>
: Proxy <O> & IProxiedObservable<O>
;

// RxJS Observable with pipe method, returning Proxify
export type ProxiedPipeObservable<O> = Omit<Observable<O>, 'pipe'> & {
// Basic proxy with props as proxify
export type Proxy<O> = { [P in keyof O]: Proxify<O[P]> };

// Callable Proxied Observable
interface ICallableProxiedObservable<O extends (...args: any[]) => R, R> extends IProxiedObservable<O> {
(...args: Parameters<O>): Proxify<R>;
}

// Observable with pipe method, returning Proxify
interface IProxiedObservable<O> extends Observable<O> {
pipe(): Proxify<O>;
pipe<A>(op1: OperatorFunction<O, A>): Proxify<A>;
pipe<A, B>(
Expand Down Expand Up @@ -186,5 +191,3 @@ export type ProxiedPipeObservable<O> = Omit<Observable<O>, 'pipe'> & {
...operations: OperatorFunction<any, any>[]
): Proxify<{}>;
};

export type Proxy<O> = { [P in keyof O]: Proxify<O[P]> };
33 changes: 24 additions & 9 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe('Proxify', () => {
});

it('should pass the args', () => {
const a = (x, y) => x + y;
const a = (x: number, y: number) => x + y;
const o = of({ a }, { a }, { a });
const p = proxify(o);
sub = p.a(1, 1).subscribe(observer);
Expand All @@ -136,6 +136,29 @@ describe('Proxify', () => {
expect(p.a === p.a).toBe(true);
});

// TS:
// proxify(fn)() -- should be Proxify
test('Fn call result should be of type Proxify', () => {
const o = of(() => 'Hello', () => 'World');
const p = proxify(o);
// fn call
p().subscribe((s: string) => observer.next(s));
expect(observer.next).toHaveBeenCalledWith('Hello');
expect(observer.next).toHaveBeenCalledWith('World');
observer.next.mockClear();
// mapped
p.pipe(map(f => f())).subscribe(observer);
expect(observer.next).toHaveBeenCalledWith('Hello');
expect(observer.next).toHaveBeenCalledWith('World');
});

// TYPES: proxify(of('a', 'b')).length -- should be Proxify
// test('elemental types should be Proxify', () => {
// const o = of('Hello', 'World');
// const p = proxify(o);
// p.length.subscribe(console.log);
// });

// This test fails on typecheck due to `a` being
// (x: any, y: any) => { b: any }
// any type on b seem to corrupt further typings
Expand All @@ -148,13 +171,5 @@ describe('Proxify', () => {
// expect(observer.next.mock.calls).toEqual([[1], [2], [3]])
// expect(observer.complete.mock.calls.length).toBe(1);
// });

// This test fails on typecheck:
// proxify(fn)() -- is not Proxify
// test('Fn should be of type Proxify', () => {
// const o = of(() => 'Hello', () => 'World');
// const p = proxify(o);
// p.pipe(filter(x => x)).subscribe(f => f());
// });
});
});

0 comments on commit fde934f

Please sign in to comment.