From fded4584ecf18b578da3fe1fdf94d7afe02ceb85 Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Tue, 2 Jul 2024 20:57:49 -0400 Subject: [PATCH 1/3] fix(toInt): avoid throwing on symbol input --- src/number/toInt.ts | 28 +++++++++++++++++++-------- tests/number/toInt.test.ts | 39 ++++++++++++++------------------------ 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/number/toInt.ts b/src/number/toInt.ts index e0ad3234..ed40e673 100644 --- a/src/number/toInt.ts +++ b/src/number/toInt.ts @@ -1,11 +1,23 @@ -export function toInt( +import { isSymbol } from 'radashi' + +export function toInt(value: unknown): number + +export function toInt(value: unknown, defaultValue: number): number + +export function toInt( + value: unknown, + defaultValue: T, +): number | Exclude + +export function toInt( value: any, defaultValue?: T, -): number | T { - const def = defaultValue === undefined ? 0 : defaultValue - if (value === null || value === undefined) { - return def - } - const result = Number.parseInt(value) - return Number.isNaN(result) ? def : result +): number | Exclude { + // Symbols throw on string coercion, which parseInt does. + const parsedValue = isSymbol(value) ? Number.NaN : Number.parseInt(value) + return Number.isNaN(parsedValue) + ? defaultValue !== undefined + ? (defaultValue as Exclude) + : 0 + : parsedValue } diff --git a/tests/number/toInt.test.ts b/tests/number/toInt.test.ts index 48cb0d94..22321a29 100644 --- a/tests/number/toInt.test.ts +++ b/tests/number/toInt.test.ts @@ -17,31 +17,20 @@ describe('toInt', () => { const result = _.toInt({}) expect(result).toBe(0) }) - test('converts 20 correctly', () => { - const result = _.toInt('20') - expect(result).toBe(20) + test('do not throw on symbols', () => { + expect(_.toInt(Symbol())).toBe(0) }) -}) - -describe('isInt', () => { - class Data {} - test('returns false for non-number values', () => { - expect(_.isInt(undefined)).toBeFalsy() - expect(_.isInt(null)).toBeFalsy() - expect(_.isInt(false)).toBeFalsy() - expect(_.isInt(new Data())).toBeFalsy() - expect(_.isInt(Number.NaN)).toBeFalsy() - expect(_.isInt([1, 2, 3])).toBeFalsy() - expect(_.isInt({})).toBeFalsy() - expect(_.isInt('abc')).toBeFalsy() - expect(_.isInt(String('abc'))).toBeFalsy() - }) - test('returns true for int', () => { - const result = _.isInt(22) - expect(result).toBeTruthy() - }) - test('returns false for float', () => { - const result = _.isInt(22.0567) - expect(result).toBeFalsy() + test('convert "20" to 20', () => { + expect(_.toInt('20')).toBe(20) + }) + test('convert 1.23 to 1', () => { + expect(_.toInt(1.23)).toBe(1) + }) + test('convert infinite values to default', () => { + expect(_.toInt(Number.POSITIVE_INFINITY, 1)).toBe(1) + expect(_.toInt(Number.NEGATIVE_INFINITY, 1)).toBe(1) + }) + test('convert NaN to default', () => { + expect(_.toInt(Number.NaN, 1)).toBe(1) }) }) From 5849ea605ed16d2788a2896f47a649405f1f8709 Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:44:39 -0400 Subject: [PATCH 2/3] fix(toFloat): avoid throwing on symbol input --- src/number/toFloat.ts | 28 ++++++++++++++++++++-------- tests/number/toFloat.test.ts | 15 ++++++++++++--- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/number/toFloat.ts b/src/number/toFloat.ts index 314d9821..5aa57d88 100644 --- a/src/number/toFloat.ts +++ b/src/number/toFloat.ts @@ -1,11 +1,23 @@ -export function toFloat( +import { isSymbol } from 'radashi' + +export function toFloat(value: unknown): number + +export function toFloat(value: unknown, defaultValue: number): number + +export function toFloat( + value: unknown, + defaultValue: T, +): number | Exclude + +export function toFloat( value: any, defaultValue?: T, -): number | T { - const def = defaultValue === undefined ? 0.0 : defaultValue - if (value === null || value === undefined) { - return def - } - const result = Number.parseFloat(value) - return Number.isNaN(result) ? def : result +): number | Exclude { + // Symbols throw on string coercion, which parseFloat does. + const parsedValue = isSymbol(value) ? Number.NaN : Number.parseFloat(value) + return Number.isNaN(parsedValue) + ? defaultValue !== undefined + ? (defaultValue as Exclude) + : 0 + : parsedValue } diff --git a/tests/number/toFloat.test.ts b/tests/number/toFloat.test.ts index ec559eda..87efb537 100644 --- a/tests/number/toFloat.test.ts +++ b/tests/number/toFloat.test.ts @@ -17,8 +17,17 @@ describe('toFloat', () => { const result = _.toFloat({}) expect(result).toBe(0.0) }) - test('converts 20.00 correctly', () => { - const result = _.toFloat('20.00') - expect(result).toBe(20.0) + test('do not throw on symbols', () => { + expect(_.toFloat(Symbol())).toBe(0) + }) + test('convert "12.34" to 12.34', () => { + expect(_.toFloat('12.34')).toBe(12.34) + }) + test('preserve infinite values', () => { + expect(_.toFloat(Number.POSITIVE_INFINITY)).toBe(Number.POSITIVE_INFINITY) + expect(_.toFloat(Number.NEGATIVE_INFINITY)).toBe(Number.NEGATIVE_INFINITY) + }) + test('convert NaN to default', () => { + expect(_.toFloat(Number.NaN, 1)).toBe(1) }) }) From 6e4de88dc2c731c4f438f4edb9e4230c4f4f744f Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:45:59 -0400 Subject: [PATCH 3/3] chore: simplify tests --- tests/number/toFloat.test.ts | 12 ++++-------- tests/number/toInt.test.ts | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/tests/number/toFloat.test.ts b/tests/number/toFloat.test.ts index 87efb537..b67edb0a 100644 --- a/tests/number/toFloat.test.ts +++ b/tests/number/toFloat.test.ts @@ -2,20 +2,16 @@ import * as _ from 'radashi' describe('toFloat', () => { test('handles null', () => { - const result = _.toFloat(null) - expect(result).toBe(0.0) + expect(_.toFloat(null)).toBe(0.0) }) test('handles undefined', () => { - const result = _.toFloat(undefined) - expect(result).toBe(0.0) + expect(_.toFloat(undefined)).toBe(0.0) }) test('uses null default', () => { - const result = _.toFloat('x', null) - expect(result).toBeNull() + expect(_.toFloat('x', null)).toBeNull() }) test('handles bad input', () => { - const result = _.toFloat({}) - expect(result).toBe(0.0) + expect(_.toFloat({})).toBe(0.0) }) test('do not throw on symbols', () => { expect(_.toFloat(Symbol())).toBe(0) diff --git a/tests/number/toInt.test.ts b/tests/number/toInt.test.ts index 22321a29..27ef2b3b 100644 --- a/tests/number/toInt.test.ts +++ b/tests/number/toInt.test.ts @@ -2,20 +2,16 @@ import * as _ from 'radashi' describe('toInt', () => { test('handles null', () => { - const result = _.toInt(null) - expect(result).toBe(0) + expect(_.toInt(null)).toBe(0) }) test('uses null default', () => { - const result = _.toInt('x', null) - expect(result).toBeNull() + expect(_.toInt('x', null)).toBeNull() }) test('handles undefined', () => { - const result = _.toInt(undefined) - expect(result).toBe(0) + expect(_.toInt(undefined)).toBe(0) }) test('handles bad input', () => { - const result = _.toInt({}) - expect(result).toBe(0) + expect(_.toInt({})).toBe(0) }) test('do not throw on symbols', () => { expect(_.toInt(Symbol())).toBe(0)