Skip to content

Commit affd6af

Browse files
authored
allow non-zero-prefixed decimals in string.numeric (#1333)
1 parent 965d118 commit affd6af

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

ark/schema/__tests__/morphs.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ contextualize(() => {
1515
attest(parseNumber.in.json).snap({
1616
domain: "string",
1717
pattern: [
18-
"^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d*[1-9])?)|\\.\\d*[1-9]?))$"
18+
"^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d*[1-9])?)?))$"
1919
],
2020
meta: "a well-formed numeric string"
2121
})

ark/type/__tests__/keywords/parse.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ contextualize(() => {
55
it("number", () => {
66
const parseNum = type("string.numeric.parse")
77
attest(parseNum("5")).equals(5)
8+
attest(parseNum(".5")).equals(0.5)
89
attest(parseNum("5.5")).equals(5.5)
910
attest(parseNum("five").toString()).snap(
1011
'must be a well-formed numeric string (was "five")'

ark/type/__tests__/pipe.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ contextualize(() => {
780780
>`)
781781

782782
attest(t.expression).snap(
783-
"{ l: 1, n: (In: string /^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d+)?)?))$/) => Out<number> } | { n: (In: string /^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d+)?)?))$/) => Out<number>, r: 1 }"
783+
"{ l: 1, n: (In: string /^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d+)?)|\\.\\d+?))$/) => Out<number> } | { n: (In: string /^(?:(?!^-0\\.?0*$)(?:-?(?:(?:0|[1-9]\\d*)(?:\\.\\d+)?)|\\.\\d+?))$/) => Out<number>, r: 1 }"
784784
)
785785
attest(t({ l: 1, n: "234" })).snap({ l: 1, n: 234 })
786786
attest(t({ r: 1, n: "234" })).snap({ r: 1, n: 234 })

ark/util/__tests__/numbers.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { attest, contextualize } from "@ark/attest"
2-
import { nearestFloat } from "@ark/util"
2+
import { isNumericString, isWellFormedNumber, nearestFloat } from "@ark/util"
33

44
contextualize(() => {
55
describe("nearestFloat", () => {
@@ -25,4 +25,45 @@ contextualize(() => {
2525
attest(nearestFloat(-5555555555555555, "-")).equals(-5555555555555556)
2626
})
2727
})
28+
29+
describe("number matchers", () => {
30+
it("wellFormedNumberMatcher rejects decimal-only numbers", () => {
31+
attest(isWellFormedNumber(".5")).equals(false)
32+
attest(isWellFormedNumber("0.5")).equals(true)
33+
})
34+
35+
it("numericStringMatcher accepts decimal-only numbers", () => {
36+
attest(isNumericString(".5")).equals(true)
37+
attest(isNumericString("0.5")).equals(true)
38+
})
39+
40+
it("wellFormedNumberMatcher rejects trailing zeros in decimals", () => {
41+
attest(isWellFormedNumber("0.10")).equals(false)
42+
attest(isWellFormedNumber("0.1")).equals(true)
43+
})
44+
45+
it("numericStringMatcher accepts trailing zeros in decimals", () => {
46+
attest(isNumericString("0.10")).equals(true)
47+
attest(isNumericString("0.1")).equals(true)
48+
})
49+
50+
it("both matchers reject negative zero", () => {
51+
attest(isWellFormedNumber("-0")).equals(false)
52+
attest(isNumericString("-0")).equals(false)
53+
})
54+
55+
it("both matchers accept valid integers", () => {
56+
attest(isWellFormedNumber("123")).equals(true)
57+
attest(isNumericString("123")).equals(true)
58+
attest(isWellFormedNumber("-123")).equals(true)
59+
attest(isNumericString("-123")).equals(true)
60+
})
61+
62+
it("both matchers accept valid decimals", () => {
63+
attest(isWellFormedNumber("123.456")).equals(true)
64+
attest(isNumericString("123.456")).equals(true)
65+
attest(isWellFormedNumber("-123.456")).equals(true)
66+
attest(isNumericString("-123.456")).equals(true)
67+
})
68+
})
2869
})

ark/util/numbers.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export type NonNegativeIntegerLiteral<n extends bigint = bigint> =
1313
| `${Digit}`
1414
| (`${Exclude<Digit, 0>}${string}` & `${n}`)
1515

16-
/**
16+
/*
1717
* The goal of the number literal and bigint literal regular expressions is to:
1818
*
1919
* 1. Ensure definitions form a bijection with the values they represent.
@@ -42,7 +42,7 @@ const createNumberMatcher = (opts: CreateNumberMatcherOptions) =>
4242
RegexPatterns.nonCapturingGroup(opts.decimalPattern) +
4343
"?"
4444
) +
45-
(opts.allowDecimalOnly ? "" : "|" + opts.decimalPattern) +
45+
(opts.allowDecimalOnly ? "|" + opts.decimalPattern : "") +
4646
"?"
4747
)
4848
)
@@ -73,6 +73,9 @@ export const numericStringMatcher: RegExp = createNumberMatcher({
7373
allowDecimalOnly: true
7474
})
7575

76+
export const isNumericString =
77+
numericStringMatcher.test.bind(numericStringMatcher)
78+
7679
export const numberLikeMatcher = /^-?\d*\.?\d*$/
7780
const isNumberLike = (s: string) => s.length !== 0 && numberLikeMatcher.test(s)
7881

0 commit comments

Comments
 (0)