4

I have the following scenario:

// Some library
interface Bar<T> {
  something: T
}

export function foo<T>(b: Bar<T>) {}

// In my code
function anotherFoo(param1: ???) {
  MyLib.foo(param1);
}

Where ??? is my unknown

Bar is not exported, so intuitively I tried:

type param<T> = Parameters<typeof foo<T>>[0];

function anotherFoo<X>(param1: param<X>) {
  MyLib.foo(param1);
}

But type definition is illegal.

When using type param = Parameters<typeof foo>[0]; typeof seems to infer unknown, i.e. Bar<unknown>

What should ??? be?

EDIT: My actual scenario

import { Observable, of } from 'rxjs';
import { useDispatch, useSelector } from 'react-redux';

type Items = string[];
interface AppStore {
    items: Items
}

type SelectFn = Parameters<typeof useSelector>[0];

function useSelectorAsStream<T>(selectFn: SelectFn) {
    const items = useSelector<AppStore, T>(selectFn);
    const obs: Observable<T> = of(items);
    return obs;
}

function PartialReactComponent() {
    const myItems: Observable<Items> = useSelectorAsStream<Items>(store => store.items);
}
12
  • This seems simple (to me, only a journeyman level TS guy), and yet...I'm really struggling to manage it. :-) Commented Mar 10, 2021 at 10:24
  • If you function anotherFoo<X>(...args: Parameters<typeof foo<X>>) { MyLib.foo(...args); ... ? Commented Mar 10, 2021 at 10:24
  • @spender - That ends up with unknown as well. (You can try things out on the playground). Commented Mar 10, 2021 at 10:28
  • @Paul Felice please let me know if next solution works for you typescriptlang.org/play?#code/… Commented Mar 10, 2021 at 10:30
  • 1
    @captain-yossarian I like the solution but it's not good I'm afraid cause I don't have access to Bar when I declare anotherFoo Commented Mar 10, 2021 at 10:34

1 Answer 1

2

I believe this should work for you:

import { Observable, of } from 'rxjs';
import { useDispatch, useSelector } from 'react-redux';

type Items = string[];
interface AppStore {
    items: Items
}

type SelectFn<T> = (state: AppStore) => T

function useSelectorAsStream<T>(selectFn: SelectFn<T>) {
    const items = useSelector<AppStore, T>(selectFn);
    const obs: Observable<T> = of(items);
    return obs;
}

function PartialReactComponent() {
    const myItems = useSelectorAsStream<Items>(store => store.items);
}

Playground

UPDATE

With typeof for safety:

import { Observable, of } from 'rxjs';
import { useDispatch, useSelector } from 'react-redux';

type Items = string[];
interface AppStore {
    items: Items
}

type SelectFn<T> = (state: AppStore) => T

type Result<T> =
    typeof useSelector extends <State, Selected>(cb: SelectFn<T>) => T
    ? SelectFn<T>
    : never


function useSelectorAsStream<T>(selectFn: Result<T>) {
    const items = useSelector<AppStore, T>(selectFn);
    const obs: Observable<T> = of(items);
    return obs;
}

function PartialReactComponent() {
    const myItems: Observable<Items> = useSelectorAsStream<Items>(store => store.items);
}
Sign up to request clarification or add additional context in comments.

1 Comment

@captain-yossarian I actually think this solves my original problem :) I'm still curious if it can be done using typeof, but it can be for another day.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.