Home > Software design >  Infer type from function in a promise block in TypeScript
Infer type from function in a promise block in TypeScript

Time:10-17

I'm very new to typescript and I wanted to try and reduce my usage of try...catch blocks by creating a one liner method. the issue that I have is that I don't know how to infer or create a correct return type that my VS code intenseness recognizes the result value.

I was initially trying to get it to work using generic types but I don't think that's the correct approach.

// My try catch block
async function solve<T>(fn: T) {
  const res = await fn;
  if(res)
    return [res, false];
  return [null, true];
}

(async ()=>{
  const [a, b] = await solve(new Promise(resolve => {
    setTimeout(()=>{
      resolve({
        n: 1
      })
    }, 2000)
  }));

  // I want to get suggestion that "n" is a property of returned "a".
  console.log(a)
  // this gives typescript error
  console.log(a.n)

})();

CodePudding user response:

Well, Firstly you need to annotate your functions and Promises with the correct type information. So your solve method should look like this :

async function solve<T>(fn: Promise<T> | PromiseLike<T>): Promise<[T, false] | [null, true]> {
  const res = await fn;
  if (res)
    return [res, false];
  return [null, true];
}

And you should call your function with the generic Promise<T> :

const [a, err] = await solve(new Promise<{ n: number }>(resolve => {
    setTimeout(() => {
      resolve({
        n: 1
      })
    }, 2000)
  }));

Even if you do so you will need a not-null assertion to bypass the possible null exception like below :

if (!err) {
    // I want to get suggestion that "n" is a property of returned "a".
    console.log(a)
    // this gives possible null exception but  I think its a limitation.
    console.log(a!.n)
  }

This is some kind of limitation of Typescript it fails to narrow down the type correctly depending on the array elements. If you were using an object instead of an array it would work without exception :

async function solve2<T>(fn: Promise<T>): Promise<{ result: T, isError: false } | { result: null, isError: true }> {
  const res = await fn;
  if (res)
    return { result: res, isError: false };

  return { result: null, isError: true };
}

 if (!res.isError) {
    console.log(res.result)
    console.log(res.result.n) // n is inferred correctly and no possible null exception here 
  }

Playground

  • Related