0

I have a custom hook like this, I want to make request parameter optional and response required:

function useRequest<T, S = any>(api: (input?: S) => Promise<T>) {
  const [response, setResponse] = useState<T | null>(null);

  const fetchData = useCallback(
    (input?: S) => {
      api(input)
        .then((data) => {
          setResponse(data as T);
        })
    },
    [api],
  );
  return { response, fetchData };
}

Basically I want to call useRequest like this:

function A()
{
  //return a promise
}
function B(p1: boolean) {
  //return a promise
}

useRequest<ResponseA>(A)
useRequest<ResponseB, boolean>(B)

but I cannot use second one since the boolean is not compatible with boolean | undefined.

1
  • changing function B(p1: boolean) to function B(p1?: boolean) also works Commented Feb 13, 2020 at 15:17

1 Answer 1

2

You don't have to limit yourself to just one parameter, using tuples in rest parameters you can capture the type of the parameters and spread them back out to a new function. The effect of this is that the arity of the function is preserved:

import { useState, useCallback} from 'react'

function useRequest<T, P extends any[]>(api: (...params: P) => Promise<T>) {
  const [response, setResponse] = useState<T | null>(null);

  const fetchData = useCallback(
    (...params: P) => {
      api(...params)
        .then((data) => {
          setResponse(data as T);
        })
    },
    [api],
  );
  return { response, fetchData };
}


type ResponseA = { a: string }
type ResponseB = { b: string }
declare function A(): Promise<ResponseA>;
declare function B(p1: boolean): Promise<ResponseB>;

useRequest(A)
useRequest(B)

Playground Link

Sign up to request clarification or add additional context in comments.

Comments

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.