Typescript: Using typeof with generics

Viewed 60

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);
}
1 Answers

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);
}
Related