LeetCode-OpenSource/rxjs-hooks

Typing error when wrapping useObservable with generic

dfee opened this issue · 1 comments

dfee commented
import { useObservable } from "rxjs-hooks";
import { map  } from "rxjs/operators";

export const useAsync = <State, Inputs extends any[]>(
  fn: (...args: Inputs) => State,
  deps: Inputs,
) =>
  useObservable<State, Inputs>(
    inputs$ =>
      inputs$.pipe(
        map(i => {
          return (i as unknown) as State;
        }),
      ),
    [0, 1, 2],
    deps,
  );

Results in the following:
image

It seems that passing generic values for useObservable isn't supported. Any ideas?

dfee commented

Here's a more contextual example (and a repl.it demo):

import { useObservable } from 'rxjs-hooks';
import { Observable, from, of } from 'rxjs';
import { catchError, map, switchMap, startWith } from 'rxjs/operators'

export type AsyncState<T> =
  | { loading: true; result?: never; error?: never }
  | {
    loading: false;
    result: T extends Promise<infer U> ? U : T;
    error?: never;
  }
  | { loading: false; result?: never; error: Error };

export const useAsync = <T, D extends any[]>(
  fn: (...args: D) => T | Promise<T>,
  deps: D,
) =>
  // https://github.com/LeetCode-OpenSource/rxjs-hooks/blob/master/src/use-observable.ts#L12-L16
  useObservable<AsyncState<T>, D>(
    inputs$ =>
      inputs$.pipe(
        switchMap(
          inputs =>
            from(Promise.resolve(fn(...inputs))).pipe(
              map(r => ({ loading: false, result: r })),
              catchError((err: Error) => of({ loading: false, error: err })),
              startWith({ loading: true }),
            ),
        ),
      ),
    { loading: true },
    deps,
  );

As you can see, I'm effectively creating a standardized way for my app to handle async requests.

The problem though, is the same:

TypeScript v3.3.3 linux/amd64

/usr/local/lib/node_modules/ts-node-fm/src/index.ts:226
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
index.ts:20:5 - error TS2345: Argument of type '(inputs$: Observable<any[]>) => Observable<{ loading: boolean; result: any; } | { loading: boolean; error: Error; } | { loading: boolean; }>' is not assignable to parameter of type 'InputFactory<AsyncState<T>, D>'.

 20     inputs$ =>
        ~~~~~~~~~~
 21       inputs$.pipe(
    ~~~~~~~~~~~~~~~~~~~
...
 29         ),
    ~~~~~~~~~~
 30       ),
    ~~~~~~~
index.ts:24:37 - error TS2345: Argument of type 'any[]' is not assignable to parameter of type 'D'.

24             from(Promise.resolve(fn(...inputs))).pipe(
                                       ~~~~~~~~~

    at createTSError (/usr/local/lib/node_modules/ts-node-fm/src/index.ts:226:12)
    at getOutput (/usr/local/lib/node_modules/ts-node-fm/src/index.ts:335:40)
    at Object.compile (/usr/local/lib/node_modules/ts-node-fm/src/index.ts:368:11)
    at startRepl (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:147:28)
    at Object.<anonymous> (/usr/local/lib/node_modules/ts-node-fm/src/bin.ts:66:1)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Module.load (internal/modules/cjs/loader.js:566:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:506:12)