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
function actual(value: string|number) {
let numbers = new Set<number>();
if (numbers.has(value)) // Error: Type 'string' is not assignable to type 'number'.
value
// we need to do
if (numbers.has(value as number))
value = value as number
}
declare class MySet<T> {
has(elem: any): elem is T;
}
function suggested(value: string|number)
let numbers = new MySet<number>();
if (numbers.has(value)) // OK, we are doing a legal checking
value // <= value is a 'number'
}
thank you for your attention.
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 Set<T> doesn't contain a value, then the value isn't of type T?
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 Set:
// put this in your own code to reap its benefits
interface Set<T> {
has(elem: any): elem is T;
}
Cheers!
Duplicate of https://github.com/Microsoft/TypeScript/issues/13086
It's not a duplicate; #13086 is about performing a get() after a has(). This is... something else.
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 has is just used just as non-undefined typeguard, still be really useful? I often have situations along the lines of:
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 map.get(key) in the if's clause must return not-undefined thanks to that has.
@fasiha you are looking for #13086
Agree with @jcalz this doesn't seem like a good solution (to say nothing of the problem)
Most helpful comment
I don't think this is a great idea, for a few reasons. The most obvious one is this:
If a
Set<T>doesn't contain a value, then the value isn't of typeT?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:
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
Set:Cheers!