-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Fixes Number.is* signatures to accept any input. #24436
Conversation
These functions are incredibly useful for testing to see if a value is a number that meets certain constraints as they return false for _any_ input that doesn't satisfy the constraints explicitly. Tested in NodeJS and Firefox and both of them work properly when you give a range of values. MDN also indicates that they will return false for any non-number input.
Already declined, see #4002. |
TL;DR: The arguments made in that PR do not apply here, and this is not a duplicate. @j-oliveras That is for Because of the lack of implicit conversion, there are very meaningful and useful use cases for calling |
Sorry, you are right. |
@RyanCavanaugh thoughts? |
I think it's compelling to allow e.g. That said, I'm not a huge fan that you can write e.g. Without the ability to declare contravariant parameters or use the assignability relationship for some parameter positions, though, I think the first point outweighs the second. |
@RyanCavanaugh Already doable: declare function isFinite<T extends (number extends T ? any : number)>(
value: T,
): boolean;
declare const maybeNumber: number | string;
declare const definitelyNumber: number;
declare const definitelyNotNumber: string;
isFinite("oops") // Argument of type '"oops"' is not assignable to parameter of type 'number'
isFinite(12345) // allowed
isFinite(maybeNumber) // allowed
isFinite(definitelyNumber) // allowed
isFinite(definitelyNotNumber) // Argument of type 'string' is not assignable to parameter of type 'number' Credit to @jcalz for coming up with the pattern in an old issue #22375 (comment). I have it bookmarked because it's so useful. |
Do I understand correctly that what you want is for function a(x: number|string, y: string, z: any) {
Number.isFinite(x) // no compiler error
Number.isFinite(y) // compiler error
Number.isFinite(z) // no compiler error
} |
Also, would it be appropriate for me to change the signatures in this PR to have the return value as function a(input: any) {
if (!Number.isFinite(input)) throw new Error(`${input} must be a finite number.`)
// `input` is now of type `number` at this point in the code according to the compiler I can also submit that as a separate PR if that is preferable. |
@MicahZoltu unfortunately making these functions act as typeguard ( IIRC there was an issue to add typeguards that only narrow the then-branch, but I can't find it right now. |
I skipped straight to a PR rather than opening an issue first because this is such a small change and a PR illustrates the problem well IMO. I can open a separate issue if that is desirable.
These functions are incredibly useful for testing to see if a value is a number that meets certain constraints as they return false for any input that doesn't satisfy the constraints explicitly. Tested in NodeJS and Firefox and both of them work properly when you give a range of values. MDN also indicates that they will return false for any non-number input.