Search code examples
node.jstypescripttypescript-typings

typescript infer never[] when returned empty array from catch statement with async/await method


method getData() returns Promise<Output[]> without catch statement type of data inferred is Output[]

but when I try to put catch statement in front of getData() method type of data becomes Output[] | void and I can understand that if there is an error while getting data then I am not returning anything from catch block.

When I try to return an empty array from catch statement type of data that typescript is inferring is Output[] | never[]. I am not able to understand the concept of never[]

I am not able to grasp the concept of never[]. and what would be the best practice/solution in this case to handle error and get the intended type of array instead of void or never.

  const data = await getData().catch((e) => {
    handleError(e);
    return [];
  });

Solution

  • when you're using async/await, the general approach is to wrap it with try/catch. This helps with typescript inferring the type.

    For example,

    async function getData() {
      return [1];
    }
    
    // inferred as `number[] | never[]` because .catch adds additional types. 
    // The returned value could be the type from getData or the type from the catch function. 
    // Promise<number[]>.catch<never[]>
    const data = await getData().catch(e => {
      ...
    })
    

    Whereas if you wrap it with try/catch

      try {
        // inferred as `number[]`
        const data = await getData();
        return data;
      } catch (e) {
        handleError(e);
        return [];
      }
    

    Here is a full example.

    async function getData() {
      return [1];
    }
    
    function handleError(e: any) {
      console.log(e);
    }
    
    async function main() {
      try {
        const data = await getData();
        return data;
      } catch (e) {
        handleError(e);
        return [];
      }
    }
    
    main();