-
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
SUGGESTION: Set and Map '.has' method as type guard #18781
Comments
I don't think this is a great idea, for a few reasons. The most obvious one is this: declare let numbers: Set<number>;
declare let value: string | number;
if (numbers.has(value)) {
value + 2 // narrowed to number, okay
} else {
value.charAt(0); // narrowed to string?!
} If a Less obvious but possibly more important is that such a declaration subverts the point of type checking. Mistakes like this will no longer be caught: let nums = [0, 1, 2]; // array of numbers
numbers.has(nums); // oops, no error! So I wouldn't want to see this added to the standard libraries. If these objections don't sway you and you still find this change useful for your own work, you could always modify or augment your local declaration of // put this in your own code to reap its benefits
interface Set<T> {
has(elem: any): elem is T;
} Cheers! |
Duplicate of #13086 |
It's not a duplicate; #13086 is about performing a |
Is there a very compelling scenario for this? I get the idea, but like @jcalz said, this means you could easily screw up and pass anything accidentally which lead to some frustrating behavior. There's nothing super wrong with adding your own overload if you feel it'd help you out a lot. |
Wouldn't the narrower use-case, where function foo(map: Map<String, String>, key: String): String {
if (map.has(key)) {
return map.get(key); // Type 'String | undefined' is not assignable to type 'String'.
}
return "";
} It feels odd and incomplete that TypeScript doesn't know that |
Agree with @jcalz this doesn't seem like a good solution (to say nothing of the problem) |
interface Set<T> {
has<U extends T>(elem: U): elem is U;
has(elem: any): boolean; // wider case passes through
} Wouldn't this prevent the Edit: I actually tested it and it prevents wider type narrowing, but it also causes the narrow type to resolve to never in the else case. declare let numbers: Set<number>
declare let value: boolean | number
declare let value2: number
if (numbers.has(value)) {
value + 2 // no narrowing
} else {
value.charAt(0) // no narrowing
}
if (numbers.has(value2)) {
value2 + 2 // number as is.
} else {
value2.charAt(0) // narrowed to never
} |
This is a small suggestion, but I think it can be interesting to bring this type of characteristics to the spirit of the typescript language.
Code
thank you for your attention.
The text was updated successfully, but these errors were encountered: