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

Store the result of a type guard into a const but keep its type guard nature. #35603

Closed
5 tasks done
abidingotter opened this issue Dec 10, 2019 · 5 comments · Fixed by #44730
Closed
5 tasks done

Store the result of a type guard into a const but keep its type guard nature. #35603

abidingotter opened this issue Dec 10, 2019 · 5 comments · Fixed by #44730
Labels
Duplicate An existing issue was already created

Comments

@abidingotter
Copy link

abidingotter commented Dec 10, 2019

Search Terms

type guard store result const

Suggestion

Store the result of a type guard into a const but keep its "type guardiness".

Use Cases

Suppose I have some code containing a type guard:

    public MyFunc($elem: JQuery | string): void {
        if (!(typeof $elem === 'string')) {
            // compiles ok
    	    let $f = $elem.parents('form').first();
        }
    }

Here Typescript knows the $elem is not a string, so it must be a JQuery element, and the compiler is happy.

But say I want to store the result into a const (perhaps for readability and re-use of the expression)

    public MyFunc2($elem: JQuery | string): void {
        const elemIsString = (typeof $elem === 'string');
    
        if (!elemIsString) {
            // fails to compile, $elem is still "JQuery | string" here
            let $f = $elem.parents('form').first();
        }
    }

Is such a thing possible without writing a type guard function? It seems like it could be possible if the result of (typeof $elem === 'string') is not boolean, but instead is of type $elem is string type guard (but is simply emitted as a JavaScript boolean)

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@jcalz
Copy link
Contributor

jcalz commented Dec 10, 2019

Duplicate of #12184, #24865

@fatcerberus
Copy link

...and many, many others. Not even joking--this comes up at least once every few weeks. It would be nice to have, but it's a much bigger can of worms than it looks like because tsc would have to track dependencies between different variables in different scopes as opposed to simply considering each variable independently like it can today.

@abidingotter
Copy link
Author

Sorry for the duplicate. I can understand that it might get complex if $elem is reassigned in my examples. It really isn't worth killing the performance of the compiler for. It just seemed like it should work :)

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Dec 10, 2019
@fatcerberus
Copy link

fatcerberus commented Dec 10, 2019

It’s not even about whether $elem is reassigned (though that certainly complicates matters even further) - it’s about the control flow analyzer being able to say “true/false type guard on elemIsString - what does this imply for every other variable currently in scope?” which is, of course, not trivial in general.

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants