Skip to content

Infer parameter as number when using Number.is* #44664

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

Closed
wants to merge 1 commit into from

Conversation

til-schneider
Copy link

When using the Number.is* (Number.isFinite, Number.isInteger, Number.isNaN and Number.isSafeInteger), the parameter's type should be inferred as number.

Example:

function foo(value: number | null | undefined) {
    if (Number.isFinite(value)) {
        bar(value)
    }
}

function bar (value: number) {
    ...
}

When using the `Number.is*` (`Number.isFinite`, `Number.isInteger`, `Number.isNaN` and `Number.isSafeInteger`), the parameter's type should be inferred as `number`.

Example:
```typescript
function foo(value?: number) {
    if (Number.isFinite(value)) {
        bar(value)
    }
}

function bar (value: number) {
    ...
}
```
@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Jun 19, 2021
@fatcerberus
Copy link

The reason this isn't the case is because:

function isFinite(x: unknown): x is number
{
    return Number.isFinite(x);
}

let foo: number | string = Infinity as number | string;
if (!isFinite(foo)) {
    foo;  // string?!
}

Type predicates work in both directions.

@til-schneider
Copy link
Author

til-schneider commented Jun 19, 2021

@fatcerberus: This would be true for the global isFinite, but Number.isFinite returns false if you pass a string.

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite

In comparison to the global isFinite() function, this method doesn't first convert the parameter to a number. This means only values of the type number and are finite return true.

Example:

console.log(Number.isFinite('12'))   // false

@MartinJohns
Copy link
Contributor

@til-schneider Notice the negation operator before.

And see #39090 (comment).

@til-schneider
Copy link
Author

OK, I see. That's unfortunate...

So the only correct inference would be isNaN(number: unknown): number is NaN;?

@til-schneider
Copy link
Author

No, this does't work either. Only number is typeof NaN would work, but typeof NaN is number again...

@MartinJohns
Copy link
Contributor

That would be the case if NaN would be a valid type.

@til-schneider til-schneider deleted the patch-1 branch June 19, 2021 06:00
@fatcerberus
Copy link

@til-schneider Notice that I wasn’t using the built-in global isFinite in my example, but one I implemented manually exactly to illustrate the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants