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

Assignments in the try-block are unconditionally assumed to have never happened in the catch-block #16682

Closed
kujon opened this issue Jun 21, 2017 · 3 comments
Labels
Suggestion An idea for TypeScript Too Complex An issue which adding support for may be too complex for the value it adds

Comments

@kujon
Copy link
Contributor

kujon commented Jun 21, 2017

TypeScript Version: 2.4.0

Code

The following is self-explanatory and nice. There is only one way an error can be thrown, therefore the compiler can make an assumption that res never got assigned in the try-block, if the catch-block is reached.

const throwing = () => { throw new Error(); };

let res = null;

try {
    res = throwing();
} catch (ex) {
    if (res) {
        // Property 'value' does not exist on type 'never'.
        console.log(res.value);
    }
}

If we start adding to this example however, strange things happen. In the example below, the compiler makes the same assumption, even though it seems incorrect. res1 assignment succeeded and its value will be { value: 42 } in the catch-block.

const nonThrowing = () => ({ value: 42 });
const throwing = () => { throw new Error(); };

let res1 = null;
let res2 = null;

try {
    res1 = nonThrowing();
    res2 = throwing();
} catch (ex) {
    if (res1) {
        // Property 'value' does not exist on type 'never'.
        console.log(res1.value);
    }
    if (res2) {
        // Property 'value' does not exist on type 'never'.
        console.log(res2.value);
    }
}

Expected behavior:
I'm not necessarily sure how this could be solved tbh. The only naive thing that comes to my mind is to only make this assumption about the last assignment in the try-block.

@kujon
Copy link
Contributor Author

kujon commented Jul 31, 2017

Any updates on this?

@DanielRosenwasser DanielRosenwasser added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Aug 1, 2017
@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Aug 1, 2017

I think the real problem is that you can't even fall back to a declared type as so:

interface SomeOtherType { }
let res: SomeOtherType | null = null;

try {
    res = null! as SomeOtherType;
}
catch (x) {
    if (res) {
        res // has type 'never'
    }
}

@RyanCavanaugh RyanCavanaugh added Too Complex An issue which adding support for may be too complex for the value it adds and removed In Discussion Not yet reached consensus labels Jan 30, 2018
@RyanCavanaugh
Copy link
Member

We don't have any mechanisms right now for retrieving all possible exception-sourced exit points from the control flow graph. Doesn't seem worth it to add that much machinery for just this case.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Suggestion An idea for TypeScript Too Complex An issue which adding support for may be too complex for the value it adds
Projects
None yet
Development

No branches or pull requests

3 participants