Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return type of a function that calls an error throwing function #13625

Closed
anilanar opened this issue Jan 22, 2017 · 5 comments
Closed

Return type of a function that calls an error throwing function #13625

anilanar opened this issue Jan 22, 2017 · 5 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@anilanar
Copy link
Contributor

anilanar commented Jan 22, 2017

TypeScript Version: 2.1.1

Code

function throwError(message: string): void {
  throw new Error(
    preprocess(message)
  );
}

// this function causes a compile error, obviously
// because it doesn't return a number
// but throwError surely throws an error so it doesn't matter
function foo(): number {
  throwError('message');
}

My use case is I'm writing some library code, where there's an interface as follows:

interface IFoo {
  foo(): number;
}

There are some modules implementing this interface, however foo is an optional method thus not all implementations will have foo method. When someone calls foo, instead of causing a Javascript error undefined is not a function, I'd prefer to throw a more descriptive error, preferably using throwError function.

I assume this would be tricky to implement.

@anilanar anilanar changed the title Return type of a function that calls a error throwing function Return type of a function that calls an error throwing function Jan 22, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Jan 23, 2017

never is the type you need for your thorw funciton, e.g.:

function throwError(message: string): never {
    throw new Error(message);
}

then you can just use this in you other function as such:

function foo(): number {
  return throwError('message');
}

never is assignable to all other types, so a function that never returns can substitute a function that returns any other value, number in this case.

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Jan 23, 2017
@anilanar
Copy link
Contributor Author

Cool thanks!

@ghost
Copy link

ghost commented May 20, 2018

Quickly hijacking this issue for a short question. Does the explanation you gave, @mhegazy, imply one should add | never to the return types of a function if it's possible that it throws an error in one branch?

@mhegazy
Copy link
Contributor

mhegazy commented May 20, 2018

never is a type that u should not witness at runtime. It should never happen, hence the name.

So a function returns a number, that is the normal execution behavior, use that in return type annotation.

More in https://www.typescriptlang.org/docs/handbook/basic-types.html#never

@JakeTunaley
Copy link

It's worth noting that calling a function with a return type of never doesn't behave the same as just throwing an error because of unassigned variable errors:

function throwError (msg: string): never {
    throw new Error('My custom error prefix: ' + msg);
}

let myString: string;
if (Math.random() < 0.5) {
    myString = 'hello world';
} else {
    throwError('hello error');
}
console.log(myString); // [ts] Variable 'myString' is used before being assigned.

So if you're doing something like the above, you'll need to return on every function that returns never:

let myString: string;
if (Math.random() < 0.5) {
    myString = 'hello world';
} else {
    return throwError('hello error');
}
console.log(myString); // No error

Be aware, however, that since you can't return in the global scope, I don't think there's anything you can do about the error in that case other than using the definite assignment assertion:

let myString!: string;
// ...
console.log(myString); // No error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants