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

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

Closed
zpdDG4gta8XKpMCd opened this issue Mar 9, 2016 · 11 comments
Labels
Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@zpdDG4gta8XKpMCd
Copy link

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
}
@zpdDG4gta8XKpMCd zpdDG4gta8XKpMCd changed the title make the strict equality comparison operator a typeguard for string liter types make the strict equality comparison operator a typeguard for string literal types Mar 9, 2016
@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Mar 9, 2016
@aluanhaddad
Copy link
Contributor

👍

@weswigham
Copy link
Member

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

@gvkhna
Copy link

gvkhna commented Mar 17, 2016

+1

@DanielRosenwasser DanielRosenwasser added the Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined label Mar 17, 2016
@DanielRosenwasser
Copy link
Member

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

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature and removed In Discussion Not yet reached consensus labels Jun 9, 2016
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jun 9, 2016

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.

@zpdDG4gta8XKpMCd
Copy link
Author

zpdDG4gta8XKpMCd commented Jun 9, 2016

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
  }
}

@ivogabe
Copy link
Contributor

ivogabe commented Jun 15, 2016

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.

@ahejlsberg
Copy link
Member

This was just suggested again in #9314. It is related to @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.

@DanielRosenwasser
Copy link
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.

@ahejlsberg
Copy link
Member

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

@ahejlsberg
Copy link
Member

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

@DanielRosenwasser DanielRosenwasser added Fixed A PR has been merged for this issue and removed Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Aug 3, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Domain: Literal Types Unit types including string literal types, numeric literal types, Boolean literals, null, undefined Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

9 participants