Skip to content

make the strict equality comparison operator a typeguard for string literal types #7447

Description

1.9.0-dev.20160217

Code

const hey: 'hey' = 'hey';
const value = Math.random() > 0.5 ? 'hey' : 'nay';
if (value === hey) {
   // here expected value to be of type 'hey' (we just asserted it), actual string
}

Activity

  1. aluanhaddad commented on Mar 11, 2016

    @aluanhaddad
    Contributor

    👍

  2. weswigham commented on Mar 11, 2016

    @weswigham
    Member

    I had a draft of this kind of guard working in #6062, and Anders Hejlsberg (@ahejlsberg) has added some form of this guard to #7140 for at least null and undefined value types, for reference.

  3. gvkhna commented on Mar 17, 2016

    @gvkhna

    +1

  4. DanielRosenwasser commented on Mar 17, 2016

    @DanielRosenwasser
    Member

    As a note, I don't think we could narrow from string because that would cause breaking changes.

  5. added
    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this feature
    and removed on Jun 9, 2016
  6. RyanCavanaugh commented on Jun 9, 2016

    @RyanCavanaugh
    Member

    The problem here is this breaking change (and arguably undesirable behavior):

    const hey: 'hey' = 'hey';
    const value = Math.random() > 0.5 ? 'hey' : 'nay';
    if (value === hey) {
       // here expected value to be of type 'hey' (we just asserted it), actual string
      let q = value;
      if (...) {
        q = 'never mind'; // error, can't assign "never mind" to "hey"
      }
    }

    The use case for changing this isn't super compelling since you have the right operand hey of === available to you for use inside the if body already with the type you want already, so narrowing the left operand doesn't seem super useful. Obviously one or the other may have been computed and not stored, but it's still probably not worth taking a breaking change for unless we can see how it's going to make some other piece of code a lot better.

  7. zpdDG4gta8XKpMCd commented on Jun 9, 2016

    @zpdDG4gta8XKpMCd
    Author

    mind me asking, can q be string | 'hey' thank to flow analysis?
    'hey' in one context and string in another?

    const hey: 'hey' = 'hey';
    const value = Math.random() > 0.5 ? 'hey' : 'nay';
    if (value === hey) {
      let q = value; // originaly string but then asserted but then might be reassigned
      if (...) {
        q = 'never mind'; // no pasa nada
      }
    }
  8. ivogabe commented on Jun 15, 2016

    @ivogabe
    Contributor

    How is this breaking change different from other breaking changes related to narrowing? They all can cause that narrowing causes that the type of a variable is too specific. In this case it's very easy to solve it, just add : string.

  9. ahejlsberg commented on Jun 22, 2016

    @ahejlsberg
    Member

    This was just suggested again in #9314. It is related to Ivo Gabe de Wolff (@ivogabe)'s suggestion here and I'm starting to think it has some merit. Specifically, for any type guard on a reference x.y, we would also narrow x itself based on the narrowed type of x.y. It effectively generalizes discriminant type guards to work over the entire set of existing type guards.

  10. DanielRosenwasser commented on Jun 22, 2016

    @DanielRosenwasser
    Member

    To be clear, my concerns about narrowing were about narrowing from string. If you had a union of string types, I'd argue that you are probably using the strings as tags and want the narrowing behavior for things like overloads and ensuring exhaustiveness. On the other hand, narrowing from string more likely to break transitive assignments, and there is no such thing as exhaustive checking of all strings.

  11. ahejlsberg commented on Jun 22, 2016

    @ahejlsberg
    Member

    Agreed, we only want to narrow from unions of string literal types, not from the string type itself.

  12. ahejlsberg commented on Jun 29, 2016

    @ahejlsberg
    Member

    The original suggestion in this issue along with a number of other features is now implemented by #9407.

  13. added
    FixedA PR has been merged for this issue
    and removed
    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this feature
    on Aug 3, 2017
  14. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Domain: Literal TypesUnit types including string literal types, numeric literal types, Boolean literals, null, undefinedFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions