0

I have this method:

export default class ApiService {
  static makeApiCall = (
    url: string,
    normalizeCallback: (d: ResponseData) => ResponseData | null,
    callback: (d: any) => any
  ): Promise<void> => (
    ApiClient.get(url)
      .then(res => {
        callback(normalizeCallback(res.data));
      })
      .catch(error => {
        console.error(`ApiClient ${url}`, error);
      })
  )

  static getArticles = (callback: (a: Article[]) => void): Promise<void> => (
    ApiService.makeApiCall(
      'articles',
      ApiNormalizer.normalizeArticles,
      callback
    )
  )
}

On this line callback: (d: any) => any typescript yells

warning Unexpected any. Specify a different type

To show you more context, here is where I am calling the method getArticles

export const fetchArticles = (): ThunkAction<Promise<void>,{},{},AnyAction> => {
  return async (dispatch: ThunkDispatch<{}, {}, AnyAction>): Promise<void> => {
    dispatch(() => ({ type: FETCH_ARTICLES }));
             // HERE: getArticles
    return ApiService.getArticles(articles => dispatch(loadArticles(articles)));
  };
};

So how can i type that callback function properly?

2
  • Well what is it going to get and receive? It looks like it gets the result of normalizeCallback and returns void, based on its usage and the overall signature. Commented Sep 11, 2019 at 20:57
  • Hi @jonrsharpe I placed the whole method with its calls and how it is used. It receives arrays and objects as it is. Commented Sep 11, 2019 at 21:02

1 Answer 1

1

I'd write it as:

function makeApi<T>(url: string, normalizeCallback: (d: ResponseData) => T | null) {
  return function(callback: (data: T | null) => any) {
    return ApiClient.get(url)
      .then(res => {
        callback(normalizeCallback(res.data));
      })
      .catch(error => {
        console.error(`ApiClient ${url}`, error);
      });
  };
}

// in the class
static getArticles = makeApi<Article[]>("articles", ApiNormalizer.normalizeArticles)

That way, you ...

1) correctly type the data type as a generic.

2) eliminate a lot of boilerplate.

3) enclose makeApi into the module, I don't think it should be exposed through the class.

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

3 Comments

Where T comes from?
First, on function declaration: Unexpected token. A constructor, method, accessor, or property was expected.ts(1068) then on callback(normalizeCallback(res.data)); => Argument of type 'T | null' is not assignable to parameter of type 'T'.
Ah, the second was a wrong type. I think you should be able to resplve the first one on your own if you reread the answer ...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.