-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stricter Intl Bindings #65
Stricter Intl Bindings #65
Conversation
@illusionalsagacity looking like you're making great progress! |
Yeah the bulk of the API surface should be bound with what's there, could use some style review to make sure it matches the rest of the stdlib's intent. Also was it intentional before that some features not supported by Firefox were left out? |
I don't know whether it was intentional. What do you think about them being left out, should they be in your opinion? |
I lean towards including them, and letting the end user decide about when to use something or not. I did mark some things that had limited support in the records as optional however, because typing as a record and omitting the property makes it entirely unavailable to the platforms that do support it. |
bc36367
to
675bec4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously this is a fairly large pull request, I'd be happy to split it up if that helps reviewing it.
Could use some input from others who have used most of these, my personal experience is mostly with Intl.DateTimeFormat
.
@illusionalsagacity I was working on modernizing my react-intl bindings and wanted to base them on RescriptCore.Intl.DateTimeFormat when I realized that that module still needed to be fleshed out. Started doing that myself before I noticed that you had actually already created this PR. 🤦 Would really like to move this PR forward! @zth Some general questions:
E.g. type dateStyle = [#full | #long | #medium | #short] vs. type dateStyle =
| @as("full") Full
| @as("long") Long
| @as("medium") Medium
| @as("short") Short
@new external make: unit => t = "Intl.DateTimeFormat"
@new external makeWithLocale: string => t = "Intl.DateTimeFormat"
@new external makeWithLocales: array<string> => t = "Intl.DateTimeFormat"
@new external makeWithLocaleAndOptions: (string, options) => t = "Intl.DateTimeFormat"
@new external makeWithLocalesAndOptions: (array<string>, options) => t = "Intl.DateTimeFormat"
@new external makeWithOptions: (@as(json`undefined`) _, options) => t = "Intl.DateTimeFormat" it would now be possible to have a single one like this: @unboxed
type localesParam =
| String(string)
| Array(array<string>)
@new external make: (~locales: localesParam=?, ~options: options=?) => t = "Intl.DateTimeFormat" or maybe just @new external make: (~locales: array<string>=?, ~options: options=?) => t = "Intl.DateTimeFormat" What approach should we prefer? |
This way, we can do some fairly aggressive changes to Core for v11+ and uncurried (migration will be easy to do a migration script for just like now) and make the APIs as nice as possible for an uncurried world. |
@zth Ok, so it's probably best to wait for the v11 uncurried / v12 branch with this PR? So that we can use regular variants and all the other v11 goodness. What are your thoughts regarding my suggestion for the @new external make: (~locales: array<string>=?, ~options: options=?) => t = "Intl.DateTimeFormat" |
It would be good to have a separate PR with the fix for #64 to merge now though. |
IMO, the multiple |
fa62ee1
to
04a426b
Compare
What makes normal variants more ergonomic? All else being equal, I find polymorphic variants more predictable and closer to the guiding principle of familiarity for JS developers. If I look at MDN and see that I need (also it's a lot more verbose and in my own bindings I'm lazy, so that's the style that would be more consistent with my own codebase) |
There are definitively upsides to polyvariants compared to regular variants, like inline type definitions, 1:1 between what you write and what you get, etc. I however think that these things from regular variants make them more ergonomic:
Some thoughts. |
In addition to the points mentioned by @zth, my concern with polymorphic variants is this: When writing bindings, it is highly likely that you will end up using untagged (regular) variants somewhere. If you are also using polymorphic variants in other places, then this mixed usage may feel weird/inconsistent to the user of the bindings, compared to just using regular variants everywhere. Therefore I feel that we should promote the latter as best practice. (Good example: our ReScript MUI bindings.) |
In any case, we should proceed with this PR now that master is v11+ only. 🙂 @zth We could also rebase and merge it quickly and, if we decide to do the adaptations I mentioned in #65 (comment), do them in separate PRs. What do you think? |
I think it makes sense to distinguish simple "literal" enum data types, such as unions of strings where inlining the type makes more sense than defining a separate nominal type, from more complex variants with payloads ad objects and such. Ideally I'd like to see a bit more intuitive syntax for the different types of primitives, and support for booleans as well, as I think that aligns quite well with TypeScript idioms. I even use this in non-binding situations for things that map to class names, for example, such as the size and style of a component. This distinction feels very natural and intuitive to me. Right now, though, the big problem here is the one case where |
Ok, then @illusionalsagacity could you rebase the PR on the latest master, get the tests to run and add a changelog entry? Then we can merge this, and make any of the adaptations I mentioned in #65 (comment) later in separate PRs. |
2d38f3d
to
57ec0d9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks again!
* feat: common Intl polymorphic variants * feat: type-safe Intl.NumberFormat bindings * feat: Intl.DateTimeFormat options * feat: Intl.Collator * feat: Intl.ListFormat * feat: Intl.RelativeTimeFormat * feat: Intl.Segmenter * feat: Intl.Locale * feat: Intl.getCanonicalLocales & supportedValuesOf * feat: tests * feat: grouping parse * feat: Intl.PluralRules * case-sensitive :( * fix type error in node 20+ tests * docs: add changelog entry * cleanup: remove firefox v110 comments * docs: add node runtime comment * fix tests
resolves #63 and #64
gonna write some more test coverage later
resolvedOptions
localeMatcher
copy pastaoneTo21
zeroTo20
in NumberFormat, use the common one instead