Skip to content

Commit 4a0ce96

Browse files
feat: type-safe Intl.NumberFormat bindings
1 parent fde5f53 commit 4a0ce96

8 files changed

+314
-40
lines changed

src/intl/Core__Intl__NumberFormat.mjs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
2-
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
2+
3+
4+
var Grouping;
5+
6+
export {
7+
Grouping ,
8+
}
9+
/* No side effect */

src/intl/Core__Intl__NumberFormat.res

Lines changed: 216 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,235 @@
1+
module Grouping = Core__Intl__NumberFormat__Grouping
2+
13
type t
24

5+
/**
6+
An ISO 4217 currency code. e.g. USD, EUR, CNY
7+
*/
8+
type currency = string
9+
type currencyDisplay = [#symbol | #narrowSymbol | #code | #name]
10+
type currencySign = [#accounting | #standard]
11+
type notation = [#scientific | #standard | #engineering | #compact]
12+
13+
/**
14+
Used only when notation is #compact
15+
*/
16+
type compactDisplay = [#short | #long]
17+
18+
// TODO: "negative" is not yet well supported
19+
type signDisplay = [
20+
| #auto
21+
| #always
22+
| #exceptZero
23+
| #never
24+
]
25+
26+
type style = [#decimal | #currency | #percent | #unit]
27+
28+
/**
29+
Defined in https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier
30+
Only used when style is #unit
31+
*/
32+
type unitSystem = string
33+
34+
/**
35+
Only used when style is #unit
36+
*/
37+
type unitDisplay = [#long | #short | #narrow]
38+
39+
type rounding = [
40+
| #ceil
41+
| #floor
42+
| #expand
43+
| #trunc
44+
| #halfCeil
45+
| #halfFloor
46+
| #halfExpand
47+
| #halfTrunc
48+
| #halfEven
49+
]
50+
51+
type roundingPriority = [#auto | #morePrecision | #lessPrecision]
52+
53+
type roundingIncrement = [
54+
| #1
55+
| #2
56+
| #5
57+
| #10
58+
| #20
59+
| #25
60+
| #50
61+
| #100
62+
| #200
63+
| #250
64+
| #500
65+
| #1000
66+
| #2000
67+
| #2500
68+
| #5000
69+
]
70+
71+
type trailingZeroDisplay = [#auto | #stripIfInteger | #lessPrecision]
72+
73+
type options = {
74+
compactDisplay?: compactDisplay,
75+
numberingSystem?: Core__Intl__Common.numberingSystem,
76+
currency?: currency,
77+
currencyDisplay?: currencyDisplay,
78+
currencySign?: currencySign,
79+
localeMatcher?: Core__Intl__Common.localeMatcher,
80+
notation?: notation,
81+
signDisplay?: signDisplay,
82+
style?: style,
83+
/**
84+
required if style == #unit
85+
*/
86+
unit?: unitSystem,
87+
unitDisplay?: unitDisplay,
88+
useGrouping?: Grouping.t,
89+
roundingMode?: rounding, // not available in firefox v110
90+
roundingPriority?: roundingPriority, // not available in firefox v110
91+
roundingIncrement?: roundingIncrement, // not available in firefox v110
92+
/**
93+
Supported everywhere but Firefox as of v110
94+
*/
95+
trailingZeroDisplay?: trailingZeroDisplay,
96+
// use either this group
97+
minimumIntegerDigits?: Core__Intl__Common.oneTo21,
98+
minimumFractionDigits?: Core__Intl__Common.zeroTo20,
99+
maximumFractionDigits?: Core__Intl__Common.zeroTo20,
100+
// OR these
101+
minimumSignificantDigits?: Core__Intl__Common.oneTo21,
102+
maximumSignificantDigits?: Core__Intl__Common.oneTo21,
103+
}
104+
105+
type resolvedOptions = {
106+
// only when style == "currency"
107+
currency?: currency,
108+
currencyDisplay?: currencyDisplay,
109+
currencySign?: currencySign,
110+
// only when notation == "compact"
111+
compactDisplay?: compactDisplay,
112+
// only when style == "unit"
113+
unit: unitSystem,
114+
unitDisplay: unitDisplay,
115+
roundingMode?: rounding, // not available in firefox v110
116+
roundingPriority?: roundingPriority, // not available in firefox v110
117+
roundingIncrement?: roundingIncrement, // not available in firefox v110
118+
// either this group
119+
minimumIntegerDigits?: Core__Intl__Common.oneTo21,
120+
minimumFractionDigits?: Core__Intl__Common.zeroTo20,
121+
maximumFractionDigits?: Core__Intl__Common.zeroTo20,
122+
// OR these
123+
minimumSignificantDigits?: Core__Intl__Common.oneTo21,
124+
maximumSignificantDigits?: Core__Intl__Common.oneTo21,
125+
// always present
126+
locale: string,
127+
notation: notation,
128+
numberingSystem: Core__Intl__Common.numberingSystem,
129+
signDisplay: signDisplay,
130+
style: style,
131+
useGrouping: Grouping.t,
132+
}
133+
134+
type supportedLocalesOptions = {localeMatcher: Core__Intl__Common.localeMatcher}
135+
136+
type numberFormatPartType = [
137+
| #compact
138+
| #currency
139+
| #decimal
140+
| #exponentInteger
141+
| #exponentMinusSign
142+
| #exponentSeparator
143+
| #fraction
144+
| #group
145+
| #infinity
146+
| #integer
147+
| #literal
148+
| #minusSign
149+
| #nan
150+
| #plusSign
151+
| #percentSign
152+
| #unit
153+
| #unknown
154+
]
155+
156+
type numberFormatPart = {
157+
\"type": numberFormatPartType,
158+
value: string,
159+
}
160+
161+
type rangeSource = [#startRange | #endRange | #shared]
162+
163+
type numberFormatRangePart = {
164+
\"type": numberFormatPartType,
165+
value: string,
166+
source: rangeSource,
167+
}
168+
3169
@new external make: unit => t = "Intl.NumberFormat"
4170
@new external makeWithLocale: string => t = "Intl.NumberFormat"
5171
@new external makeWithLocales: array<string> => t = "Intl.NumberFormat"
6-
@new external makeWithLocaleAndOptions: (string, {..}) => t = "Intl.NumberFormat"
7-
@new external makeWithLocalesAndOptions: (array<string>, {..}) => t = "Intl.NumberFormat"
8-
@new external makeWithOptions: (@as(json`undefined`) _, {..}) => t = "Intl.NumberFormat"
172+
@new external makeWithLocaleAndOptions: (string, options) => t = "Intl.NumberFormat"
173+
@new external makeWithLocalesAndOptions: (array<string>, options) => t = "Intl.NumberFormat"
174+
@new external makeWithOptions: (@as(json`undefined`) _, options) => t = "Intl.NumberFormat"
9175

10176
@val external supportedLocalesOf: array<string> => t = "Intl.NumberFormat.supportedLocalesOf"
177+
// TODO
11178
@val
12-
external supportedLocalesOfWithOptions: (array<string>, {..}) => t =
179+
external supportedLocalesOfWithOptions: (array<string>, supportedLocalesOptions) => t =
13180
"Intl.NumberFormat.supportedLocalesOf"
14181

15-
@send external resolvedOptions: t => {..} = "resolvedOptions"
182+
@send external resolvedOptions: t => resolvedOptions = "resolvedOptions"
16183

17184
@send external format: (t, float) => string = "format"
185+
/**
186+
Not available in firefox v110
187+
*/
188+
@send
189+
external formatRange: (t, ~start: float, ~end: float) => array<string> = "formatRange"
190+
@send
191+
external formatToParts: (t, float) => array<numberFormatPart> = "formatToParts"
192+
/**
193+
Not available in firefox v110
194+
*/
18195
@send
19-
external formatToParts: (t, float) => array<{"type": string, "value": string}> = "formatToParts"
196+
external formatRangeToParts: (t, ~start: float, ~end: float) => array<numberFormatRangePart> =
197+
"formatRange"
20198

21199
@send external formatInt: (t, int) => string = "format"
200+
/**
201+
Not available in firefox v110
202+
*/
22203
@send
23-
external formatIntToParts: (t, int) => array<{"type": string, "value": string}> = "formatToParts"
204+
external formatIntRange: (t, ~start: int, ~end: int) => array<string> = "formatRange"
205+
@send
206+
external formatIntToParts: (t, int) => array<numberFormatPart> = "formatToParts"
207+
/**
208+
Not available in firefox v110
209+
*/
210+
@send
211+
external formatIntRangeToParts: (t, ~start: int, ~end: int) => array<numberFormatRangePart> =
212+
"formatRange"
24213

25214
@send external formatBigInt: (t, Core__BigInt.t) => string = "format"
215+
/**
216+
Not available in firefox v110
217+
*/
218+
@send
219+
external formatBigIntRange: (t, ~start: Core__BigInt.t, ~end: Core__BigInt.t) => array<string> =
220+
"formatRange"
221+
@send
222+
external formatBigIntToParts: (t, Core__BigInt.t) => array<numberFormatPart> = "formatToParts"
223+
/**
224+
Not available in firefox v110
225+
*/
226+
@send
227+
external formatBigIntRangeToParts: (
228+
t,
229+
~start: Core__BigInt.t,
230+
~end: Core__BigInt.t,
231+
) => array<numberFormatPart> = "formatRange"
232+
233+
@send external formatString: (t, string) => string = "format"
26234
@send
27-
external formatBigIntToParts: (t, Core__BigInt.t) => array<{"type": string, "value": string}> =
28-
"formatToParts"
235+
external formatStringToParts: (t, string) => array<numberFormatRangePart> = "formatToParts"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type t
2+
3+
external fromBool: bool => t = "%identity"
4+
external fromString: [#always | #auto | #min2] => t = "%identity"
5+
// TODO: unwrap this for consumption coming back in resolvedOptions

test/Intl__NumberFormatTest.mjs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Generated by ReScript, PLEASE EDIT WITH CARE
2+
3+
import * as Caml_option from "rescript/lib/es6/caml_option.js";
4+
5+
console.info("");
6+
7+
console.info("Intl");
8+
9+
console.info("---");
10+
11+
var currencyFormatter = new Intl.NumberFormat("fr-FR", {
12+
currency: "EUR",
13+
style: "currency"
14+
});
15+
16+
console.log(Intl.NumberFormat.supportedLocalesOf([
17+
"fr-FR",
18+
"en-US"
19+
]));
20+
21+
console.log(currencyFormatter.format(123.23));
22+
23+
var roundingFormatter = new Intl.NumberFormat(undefined, {
24+
roundingPriority: "lessPrecision",
25+
roundingIncrement: 500
26+
});
27+
28+
var groupingFormatter1 = new Intl.NumberFormat(undefined, {
29+
useGrouping: Caml_option.some(true)
30+
});
31+
32+
var groupingFormatter2 = new Intl.NumberFormat(undefined, {
33+
useGrouping: "auto"
34+
});
35+
36+
var sigFormatter = new Intl.NumberFormat(undefined, {
37+
minimumIntegerDigits: 1,
38+
minimumFractionDigits: 1,
39+
maximumFractionDigits: 1,
40+
minimumSignificantDigits: 1,
41+
maximumSignificantDigits: 1
42+
});
43+
44+
export {
45+
currencyFormatter ,
46+
roundingFormatter ,
47+
groupingFormatter1 ,
48+
groupingFormatter2 ,
49+
sigFormatter ,
50+
}
51+
/* Not a pure module */

test/Intl__NumberFormatTest.res

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
open RescriptCore
2+
3+
Console.info("")
4+
Console.info("Intl")
5+
Console.info("---")
6+
let currencyFormatter = Intl.NumberFormat.makeWithLocaleAndOptions(
7+
"fr-FR",
8+
{currency: "EUR", style: #currency},
9+
)
10+
11+
Console.log(Intl.NumberFormat.supportedLocalesOf(["fr-FR", "en-US"]))
12+
Console.log(currencyFormatter->Intl.NumberFormat.format(123.23))
13+
14+
let roundingFormatter = Intl.NumberFormat.makeWithOptions({
15+
roundingPriority: #lessPrecision,
16+
roundingIncrement: #500,
17+
})
18+
19+
let groupingFormatter1 = Intl.NumberFormat.makeWithOptions({
20+
useGrouping: Intl.NumberFormat.Grouping.fromBool(true),
21+
})
22+
let groupingFormatter2 = Intl.NumberFormat.makeWithOptions({
23+
useGrouping: Intl.NumberFormat.Grouping.fromString(#auto),
24+
})
25+
26+
let sigFormatter = Intl.NumberFormat.makeWithOptions({
27+
minimumIntegerDigits: #1,
28+
minimumFractionDigits: #1,
29+
maximumFractionDigits: #1,
30+
minimumSignificantDigits: #1,
31+
maximumSignificantDigits: #1,
32+
})

test/TempTests.mjs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,6 @@ console.log(Core__Float.fromString("0.1"));
9393

9494
console.info("");
9595

96-
console.info("Intl");
97-
98-
console.info("---");
99-
100-
var currencyFormatter = new Intl.NumberFormat("fr-FR", {
101-
currency: "EUR",
102-
style: "currency"
103-
});
104-
105-
console.log(Intl.NumberFormat.supportedLocalesOf([
106-
"fr-FR",
107-
"en-US"
108-
]));
109-
110-
console.log(currencyFormatter.format(123.23));
111-
112-
console.info("");
113-
11496
console.info("JSON");
11597

11698
console.info("---");
@@ -335,7 +317,6 @@ export {
335317
dict ,
336318
dict2 ,
337319
f ,
338-
currencyFormatter ,
339320
json ,
340321
map ,
341322
myObject ,

0 commit comments

Comments
 (0)