inferring types from an Error throwing function in Typescript?

Viewed 651

I have a function below, that checks if myValue exists before calling doSomething(), if it does not exist, it will throw. Typescript accepts this...

function myFunction(){
   if (!myValue) {
     const error = Error(errorName);
     error.name = errorName.replace(/\s+/g, "-").toLowerCase();
     throw error;
   }

   const something = doSomething(myValue);
}

The below implementation makes a Helper Function for throwing a named Error. Typescript doesn't like this, and errors that doSomething(myValue) is being passed myValue which is potentially undefined. How can I type the namedError so that it has the inferred typing from above, that it is Truthy?

function myFunction(){
   if (!myValue) {
     namedError("my value doesn't exist");
   }

   const something = doSomething(myValue);
}

function namedError(errorName: string){
  const error = Error(errorName);
  error.name = errorName.replace(/\s+/g, "-").toLowerCase();
  throw error;
};
2 Answers

Since typescript 3.7 functions that return never have the same impact in control flow analysis as a throw expression. So this will work:


let myValue: string | undefined;

function myFunction() {
  if (!myValue) {
    namedError("my value doesn't exist");
  }

  const something = doSomething(myValue);
}

function namedError(errorName: string): never {
  const error = Error(errorName);
  error.name = errorName.replace(/\s+/g, "-").toLowerCase();
  throw error;
};

function doSomething(value: string) {

}

Playground Link

Typescript null elimination doesn't work with nest function calls (unless it's an immediately invoked function expression) hence the error. You can either move the doSomething invocation into an else block, or use the type assertion operator when you are sure a value will not be null or defined.

So either:

if (!myValue) {
  namedError(...)
} else {
  const something = doSomething(myValue);
}

or

if (!myValue) {
  namedError(...)
}

// use type assertion (! postfix) to tell compiler that the value will never be null or undefined
const something = doSomething(myValue!);
Related