refactor: centralize strict numeric parsing

This commit is contained in:
Peter Steinberger
2026-03-08 02:52:44 +00:00
parent 3087893ef9
commit 2646739d23
11 changed files with 128 additions and 30 deletions

View File

@@ -1,5 +1,10 @@
import { describe, expect, it } from "vitest";
import { parseFiniteNumber } from "./parse-finite-number.js";
import {
parseFiniteNumber,
parseStrictInteger,
parseStrictNonNegativeInteger,
parseStrictPositiveInteger,
} from "./parse-finite-number.js";
describe("parseFiniteNumber", () => {
it("returns finite numbers", () => {
@@ -17,3 +22,32 @@ describe("parseFiniteNumber", () => {
expect(parseFiniteNumber(null)).toBeUndefined();
});
});
describe("parseStrictInteger", () => {
it("parses exact integers", () => {
expect(parseStrictInteger("42")).toBe(42);
expect(parseStrictInteger(" -7 ")).toBe(-7);
});
it("rejects junk prefixes and suffixes", () => {
expect(parseStrictInteger("42ms")).toBeUndefined();
expect(parseStrictInteger("0abc")).toBeUndefined();
expect(parseStrictInteger("1.5")).toBeUndefined();
});
});
describe("parseStrictPositiveInteger", () => {
it("accepts only positive integers", () => {
expect(parseStrictPositiveInteger("9")).toBe(9);
expect(parseStrictPositiveInteger("0")).toBeUndefined();
expect(parseStrictPositiveInteger("-1")).toBeUndefined();
});
});
describe("parseStrictNonNegativeInteger", () => {
it("accepts zero and positive integers only", () => {
expect(parseStrictNonNegativeInteger("0")).toBe(0);
expect(parseStrictNonNegativeInteger("9")).toBe(9);
expect(parseStrictNonNegativeInteger("-1")).toBeUndefined();
});
});

View File

@@ -1,3 +1,8 @@
function normalizeNumericString(value: string): string | undefined {
const trimmed = value.trim();
return trimmed ? trimmed : undefined;
}
export function parseFiniteNumber(value: unknown): number | undefined {
if (typeof value === "number" && Number.isFinite(value)) {
return value;
@@ -10,3 +15,28 @@ export function parseFiniteNumber(value: unknown): number | undefined {
}
return undefined;
}
export function parseStrictInteger(value: unknown): number | undefined {
if (typeof value === "number") {
return Number.isSafeInteger(value) ? value : undefined;
}
if (typeof value !== "string") {
return undefined;
}
const normalized = normalizeNumericString(value);
if (!normalized || !/^[+-]?\d+$/.test(normalized)) {
return undefined;
}
const parsed = Number(normalized);
return Number.isSafeInteger(parsed) ? parsed : undefined;
}
export function parseStrictPositiveInteger(value: unknown): number | undefined {
const parsed = parseStrictInteger(value);
return parsed !== undefined && parsed > 0 ? parsed : undefined;
}
export function parseStrictNonNegativeInteger(value: unknown): number | undefined {
const parsed = parseStrictInteger(value);
return parsed !== undefined && parsed >= 0 ? parsed : undefined;
}