-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Restrictive type on callbacks that are guaranteed to error #1613
Comments
Why do you need to explicitly specify the type argument? Your run(() => { // no <boolean>, no error
throw new Error('Failure');
}); |
It's just a small example to show the behaviour without any external dependencies, I'm struggling to think of a smaller realistic example than the promises one. An alternative that has (slightly) more semantic meaning and still errors is var result: boolean;
result = run(() => {
throw new Error('Failure');
}); A longer fully specified example with some really badly implemented promises is class Promise<T> {
constructor(private value: T, private err: any) {}
catch<U>(callback: (err: any) => U): Promise<U> {
try {
return new Promise<U>(callback(this.err), null);
} catch (err) {
return new Promise<U>(null, err);
}
}
}
function reject<T>(err: any): Promise<T> { return new Promise<T>(null, err); }
class Item { name: string }
function stuff(): Promise<Item> {
// Call into the database, whatever,
// get back an exception that contains internal implementation details.
return reject<Item>(new Error('Oh noes!'));
}
function tryStuff(): Promise<Item> {
// Hide the internal implementation details by transforming the error.
return stuff()
.catch(err => { throw new Error('Something went wrong'); });
} |
Interestingly this works var result: boolean;
result = run((): boolean => {
throw new Error('Failure');
}); but this errors var result: boolean;
result = run((): boolean => {
console.log('running');
throw new Error('Failure');
}); with
so there is some (very limited) support for this with explicit typing. The error does give me the most succinct syntax currently available to do this var result: boolean;
result = run((): any => {
console.log('running');
throw new Error('Failure');
}); but it would still be nice if the |
Yeah there's an exception specifically for that single statement pattern (ex a function body of |
I think we're considering some basic flow analysis for e.g. use before declaration, at which point we can probably extend that rule to "functions which throw on all return paths". |
@RyanCavanaugh Exactly! For now I'm using the following workaround with promises: var somePromise: Promise<T> = request<T>(args).catch((error: any): Promise<T> => {
console.log(error);
return Promise.reject<T>(reason);
}); instead of (desirable) var somePromise: Promise<T> = request<T>(args).catch((error: any): T => {
console.log(error);
throw reason;
}); |
The code references above should not be an error in TypeScript 1.8. var result: boolean;
result = run((): number => {
console.log('running');
throw new Error('Failure');
}); |
Motivation
It's sometimes very useful to be able to define callbacks that guarantee an error. For example; transforming errors in when.js promises to hide implementation details:
Unfortunately the compiler derives the type of the error handler to be
(err: any) => void
and propagates the return type through the definition ofcatch
resulting inEven if the definition of
tryStuff
is changed to force the result to the correct typethe same type is derived for the error handler and you instead get
Details
A fully specified example of the same behaviour is
which gives the error
Two possible solutions are returning null to trick the compiler into giving the callback a lenient type (I guess it defaults to
any
when the onlyreturn
returns a null), or explicitly telling the compiler that the callback can return anything.The first runs afoul of unreachable statement lints. The second is just really horrible.
Seeing as the lints are capable of determining that there is no way to return from this callback, it would be nice if the compiler could also check this and give the callback the type
() => any
when it can guarantee there is no possibility of returning.The text was updated successfully, but these errors were encountered: