Skip to content
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

Update Intl.DisplayNames types for better spec compliance #48442

Merged
merged 4 commits into from
Apr 5, 2022

Conversation

jihndai
Copy link
Contributor

@jihndai jihndai commented Mar 26, 2022

Following up on issue #48218 (to avoid creating too many issues about the same topic) and based on the work from pr #48262 , here are some additional updates to keep Intl.DisplayNames up-to-date with the spec:

These behaviors have been verified with the js code below, which should execute without issue (lines meant to recreate a TypeError have been commented, and can be uncommented for testing):

/**
 * Intl.DisplayNames.prototype.resolvedOptions().type is the same as the options.type passed to Intl.DisplayNames(locales, options) constructor
 * 
 * This can be one of "calendar", "currency", "dateTimeField", "language", "region", or "script".
 */
const dnCalendar = new Intl.DisplayNames('en', {type: 'calendar'});
console.log(dnCalendar.of('roc')); // "Minguo Calendar"
console.log(dnCalendar.resolvedOptions().type); // "calendar"
const dnCurrency = new Intl.DisplayNames(['en'], {type: 'currency'});
console.log(dnCurrency.of('USD')); // "US Dollar"
console.log(dnCurrency.resolvedOptions().type); // "currency"
const dnDateTimeField = new Intl.DisplayNames('pt', {type: 'dateTimeField'});
console.log(dnDateTimeField.of('era')); // "era"
console.log(dnDateTimeField.resolvedOptions().type); // "dateTimeField"
const dnLanguage = new Intl.DisplayNames([], {type: 'language'});
console.log(dnLanguage.of('US')); // "us"
console.log(dnLanguage.resolvedOptions().type); // "language"
const dnRegion = new Intl.DisplayNames(['en'], {type: 'region'});
console.log(dnRegion.of('BZ'));  // "Belize"
console.log(dnRegion.resolvedOptions().type); // "region"
const dnScript = new Intl.DisplayNames(['en'], {type: 'script'});
console.log(dnScript.of('Latn')); // "Latin"
console.log(dnScript.resolvedOptions().type); // "script"
/**
 * Also, when options.type === "language", resolvedOptions().languageDisplay will be either "dialect" or "standard".
 * Else, resolvedOptions.languageDisplay is undefined.
 */
const dnStd = new Intl.DisplayNames('en', {type: 'language', languageDisplay: 'standard'});
console.log(dnStd.of('en-GB')); // "English (United Kingdom)"
console.log(dnStd.resolvedOptions().languageDisplay); // "standard"
console.log(dnLanguage.resolvedOptions().languageDisplay); // "dialect"
console.log(dnCurrency.resolvedOptions().languageDisplay); // undefined

/**
 * The constructor new Intl.DisplayNames(locales, options) requires options.
 * 
 * options.type is required, while all other fields are optional.
 */
// new Intl.DisplayNames(); // TypeError: invalid_argument
// new Intl.DisplayNames('en'); // TypeError: invalid_argument
// new Intl.DisplayNames('en', {}); // TypeError: invalid_argument
console.log((new Intl.DisplayNames(undefined, {type: 'language'})).of('en-GB')); // "British English"

/**
 * locales argument can be an array of both strings and Locale(s) at the same time.
 * 
 * This applies to Intl.DisplayNames(locales, options) constructor and Intl.DisplayNames.supportedLocalesOf(locales)
 */
const localesArg = ["es-ES", new Intl.Locale("en-US")];
console.log((new Intl.DisplayNames(localesArg, {type: 'language'})).resolvedOptions().locale); // "es-ES"
console.log(Intl.DisplayNames.supportedLocalesOf(localesArg)); // ["es-ES", "en-US"]
/**
 * locales, options, and options.localeMatcher are optional in Intl.DisplayNames.supportedLocalesOf(locales, options)
 */
console.log(Intl.DisplayNames.supportedLocalesOf()); // []
console.log(Intl.DisplayNames.supportedLocalesOf(localesArg, {})); // ["es-ES", "en-US"]

The code above should behave as expected on modern browsers, tested on Chrome(99.0.4844.84) and Firefox(98.0.2). The only caveat is that "calendar", "dateTimeField", and languageDisplay are features introduced in es2022 from this proposal, so those are currently not working in the latest NodeJs LTS v16.14.2, but should work in later versions (currently working on v17.8.0).

@typescript-bot
Copy link
Collaborator

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Mar 26, 2022
Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to take this change as-is and follow up on ResolvedDisplayNamesType during the beta.

@@ -295,30 +295,32 @@ declare namespace Intl {
| "code"
| "none";

type ResolvedDisplayNamesType =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be anybody using ResolvedDisplayNamesType? If so, it should stick around around as a simple alias of DisplayNamesType

@sandersn sandersn merged commit f7c457d into microsoft:main Apr 5, 2022
@jihndai jihndai deleted the issue48218-3 branch April 6, 2022 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants