2

below is the code with the description in which I am trying to send function as an argument to another function and then use the arguments of this function in another function. the problem is I don't know how to get strong typing on service function argument.

interface Todo {
  id: number;
  name: string
}

function getTodos(arg1: string, arg2: number) {
  return axios.get<Todos[]>('/todos');
}

function useAPI<S>(service: (...args: any[]) => Promise<AxiosResponse<S>>) {
  const [isLoading, setIsLoading] = useState(false);
  const [response, setResponse] = useState<AxiosResponse<S> | undefined>(undefined);
  const [error, setError] = useState<AxiosError | undefined>(undefined);

  function doRequest(params: Parameters<typeof service>) {
    setIsLoading(true);
    setResponse(undefined);
    setError(undefined);

    service
      .apply(this, params)
      .then((r: AxiosResponse) => {
        setIsLoading(false);
        setResponse(r);
      })
      .catch((e: AxiosError) => {
        setError(e);
        setIsLoading(false);
      });
  };

  return {
    isLoading,
    response,
    error,
    doRequest,
  };
};


const TodoList: React.FC = () => {
  const todosAPI = useAPI(getTodos);


  useEffect(() => {
    if (todosAPI.response?.data) {
      console.log(todosAPI.response.data) // I have a strong typing here
    }

  }, [todosAPI.response])

  useEffect(() => {
    todosAPI.doRequest([]) // but I also want to have strong typing for service arguments - arg1, arg2
  }, [])
}


1 Answers1

1

Solution:

You can add in another generic to your useAPI function:

function useAPI<T extends Array<unknown>, S>(service: (...args: T) => Promise<AxiosResponse<S>>) {

Result:

By doing so, the typing of the todosAPI constant becomes:

const todosAPI: {
    isLoading: boolean;
    response: AxiosResponse<Todo[]> | undefined;
    error: AxiosError<any> | undefined;
    doRequest: (params: [string, number]) => void;
}

Thus doRequest is typed based on the getTodos function given.

More info:

The T generic is expected to be an Array type to allow usage of the spread operator. unknown is the typesafe counterpart of any and was introduced in TypeScript 3.0.

Sources:

Zwei
  • 1,279
  • 8
  • 16