Home > OS >  Typescript narrowing doesn't work when function is always throwing
Typescript narrowing doesn't work when function is always throwing

Time:10-06

I have a utility function which I use for throwing different kinds of errors in an organized way. It always throws an error. However, Typescript is not smart enough to use this for narrowing:

interface A {
  x: {
    a?: string;
  }
}

const g = (s: A): string => {
  if (!s.x.a) {
    throw Error("mess");
  }
  return s.x.a // compiles just fine
}

const f = (): never => {
  throw Error('message');
}

const gg = (s: A): string => {
  if (!s.x.a) {
    f()
  }
  return s.x.a // ERROR: can be undefined!
}

I thought returning never will help the compiler to be smarter, but it doesn't. Is there another way or a keyword to use to achieve this?

CodePudding user response:

You can't really have f magically make whatever condition it was called under the assertion condition, but if you pass that condition directly to f and utilize asserts, then you will come up with something that is similar to the built-in asserts function from Node.js:

function f(thing: any): asserts thing {
  if (!thing) throw Error('message');
}

Pretty uncanny resemblance with the real deal:

function assert(condition: any, msg?: string): asserts condition {
  if (!condition) {
    throw new AssertionError(msg);
  }
}

Playground

CodePudding user response:

why not just return f as you know it would throw anyways and halt the execution

const gg = (s: A): string => {
  if (!s.x.a) {
    return f()
  }
  return s.x.a // ERROR: can be undefined!
}
  • Related