Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does typescript think my property could be void after I throw in a promise catch block?

async function fetchMpdData(mpdUrl: string): Promise<MPDFileContainer> {
  const data = await fetch(mpdUrl)
    .then((response): Promise<string> => response.text())
    .catch(
      (error): void => {
        throw new FetchError(`Error fetching file ${mpdUrl}: ${error}`);
      },
    );
  return parseStringMpd(data);
}

parseStringMpd takes a string. The data passed to parseStringMpd is failing with:

Argument of type 'string | void' is not assignable to parameter of type 'string'.

There are a few other questions on SO that talk about how if the promise fails the catch block will cause the data property to be void. But in my case the catch block is throwing an error. So the data that is being complained about will never be reached.

Is the typescript parser just not able to handle this?

like image 987
Stephen Horvath Avatar asked May 30 '19 16:05

Stephen Horvath


1 Answers

Your error is here:

  (error): void => {
    throw new FetchError(`Error fetching file ${mpdUrl}: ${error}`);
  },

You declare that the return type is void (a function that returns nothing) instead of never (a function that never returns). You could change it to : never but I suggest you to let TypeScript infer it:

  error => {
    throw new FetchError(`Error fetching file ${mpdUrl}: ${error}`);
  },

… But if you use async / await you could rewrite your code with them:

async function fetchMpdData(mpdUrl: string): Promise<MPDFileContainer> {
    try {
        const response = await fetch(mpdUrl)
        const data = await response.text()
        return parseStringMpd(data);
    } catch (error) {
        throw new Error(`Error fetching file ${mpdUrl}: ${error}`)
    }
}

Notice that variables response and data are correctly typed by inference. It's useless to declare their types.

like image 50
Paleo Avatar answered Oct 07 '22 20:10

Paleo