typescriptnulltype-narrowing

Why does typescript think I have an Error when it can only be null?


I have this situation where Typescript is not behaving how I expect (n.b. I can't switch on strictNullChecks for the whole project):

const error = new Error("I'm and error");
const textError = "Also and error";

const printErrorMessage = (err: string | Error) => {
  const errorMessage = (err === null || typeof err === "string") ? err : err?.message ?? err?.name ?? 'unknown error';
  if (errorMessage) {
    console.log(errorMessage);
  }
  return errorMessage;
}

const errorMessageOne = printErrorMessage(error);
const errorMessageTwo = printErrorMessage(textError);
const errorMessageThree = printErrorMessage(null);

My hope was that the only time that err is returned as itself is if it's null or a string, but that means the return value should either be Null or string not string | Error.

screenshot of the TS playground, with a tooltip showing the return type is string 'or' Error

Because this function can be sent a null object, but I don't want to convert that to the string 'unknown error' I can't just let null slide through.

Here's my TS playground where I've confirm this happens outside of my dev environment.


Solution

  • After posting my question and playing around some more I found a temporary solution (not recommended, but I need a stop gap for the time being).

    You can change the assignment line to have a cast (not recommended!) to get around this: const errorMessage = (err === null || typeof err === "string") ? (err as null | string) : err?.message ?? err?.name ?? 'unknown error';

    Definitely follow the other answers if you're able to do so.