diff --git a/.github/next-major.md b/.github/next-major.md index f1ac2579..931d0843 100644 --- a/.github/next-major.md +++ b/.github/next-major.md @@ -37,3 +37,18 @@ The `####` headline should be short and descriptive of the breaking change. In t const func = debounce({ delay: 1000 }, mockFunc) expect(func.callee).toBe(mockFunc) ``` + +#### Change `isNumber` to return true for `NaN` values + +Returning true for NaN values allows `isNumber` to perform “type narrowing” in TypeScript without risking a runtime error. This is because NaN is not a valid type in TypeScript, so it cannot be separated from other numbers. + +```ts +const value: number | string = NaN + +if (!isNumber(value)) { + // Would previously have caused a runtime error, because `isNumber` returned false for `NaN` + value.toUpperCase() +} + +isNumber(NaN) // => true +``` diff --git a/docs/typed/isNumber.mdx b/docs/typed/isNumber.mdx index e8018e36..ae33f5e0 100644 --- a/docs/typed/isNumber.mdx +++ b/docs/typed/isNumber.mdx @@ -14,4 +14,5 @@ import * as _ from 'radashi' _.isNumber('hello') // => false _.isNumber(['hello']) // => false _.isNumber(12) // => true +_.isNumber(NaN) // => true ``` diff --git a/src/typed/isFloat.ts b/src/typed/isFloat.ts index 9e4f9f7b..834fcc67 100644 --- a/src/typed/isFloat.ts +++ b/src/typed/isFloat.ts @@ -12,5 +12,5 @@ import { isNumber } from 'radashi' * @version 12.1.0 */ export function isFloat(value: any): value is number { - return isNumber(value) && value % 1 !== 0 + return isNumber(value) && !Number.isNaN(value) && value % 1 !== 0 } diff --git a/src/typed/isNumber.ts b/src/typed/isNumber.ts index a27138a2..cb9f35fb 100644 --- a/src/typed/isNumber.ts +++ b/src/typed/isNumber.ts @@ -6,10 +6,10 @@ * ```ts * isNumber(0) // => true * isNumber('0') // => false - * isNumber(NaN) // => false + * isNumber(NaN) // => true * ``` * @version 12.1.0 */ export function isNumber(value: unknown): value is number { - return typeof value === 'number' && !Number.isNaN(value) + return typeof value === 'number' } diff --git a/tests/typed/isNumber.test.ts b/tests/typed/isNumber.test.ts index 3ed844ba..0527c297 100644 --- a/tests/typed/isNumber.test.ts +++ b/tests/typed/isNumber.test.ts @@ -26,9 +26,9 @@ describe('isNumber', () => { const result = _.isNumber(22.0567) expect(result).toBeTruthy() }) - test('returns false for NaN', () => { + test('returns true for NaN', () => { const result = _.isNumber(Number.NaN) - expect(result).toBeFalsy() + expect(result).toBeTruthy() }) test('returns false for array', () => { const result = _.isNumber([1, 2, 3])