Reputation: 1857
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
.
Upvotes: 0
Views: 54
Reputation: 250236
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)
Upvotes: 2