vue-i18n icon indicating copy to clipboard operation
vue-i18n copied to clipboard

TS5 - using numberFormats throws error

Open apmyp1990 opened this issue 2 years ago • 2 comments
trafficstars

Reporting a bug?

Before updating to TS5, everything worked fine. After the update this erro occurs on build:

 TS2769: No overload matches this call.
  Overload 1 of 2, '(options?: UseI18nOptions<{ message:
 LocaleMessage<VueMessageType>; datetime: DateTimeFormat
; number: NumberFormat; }, string, ComposerOptions<{ ...
; }, ... 9 more ..., NumberFormats<...>>> | undefined): Composer<...>', gave the following error.
    Type '{ 'de-DE': { currency: { style: string; curren
cy: string; notation: string; }; decimal: { style: strin
g; minimumFractionDigits: number; maximumFractionDigits:
 number; }; percent: { style: string; useGrouping: boole
an; }; }; }' is not assignable to type '{ [x: string]: NumberFormat; }'.
  Overload 2 of 2, '(options?: UseI18nOptions<{ message:
 LocaleMessage<VueMessageType>; datetime: DateTimeFormat
; number: NumberFormat; }, { messages: "en-US"; datetime
Formats: "en-US"; numberFormats: "en-US"; }, ComposerOpt
ions<...>> | undefined): Composer<...>', gave the following error.
    Type '{ 'de-DE': { currency: { style: string; curren
cy: string; notation: string; }; decimal: { style: strin
g; minimumFractionDigits: number; maximumFractionDigits:
 number; }; percent: { style: string; useGrouping: boole
an; }; }; }' is not assignable to type '{ "en-US": NumberFormat; }'.

22   const {n} = useI18n({locale: 'de', numberFormats}) 

I have defined the numberFormat like so:

export const numberFormats = {
    'de-DE': {
        currency: {
            style: 'currency', currency: 'EUR', notation: 'standard'
        },
        decimal: {
            style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2
        },
        percent: {
            style: 'percent', useGrouping: false
        }
    }
};

The error occurs every time I want to use the n-function: const {n} = useI18n({locale: 'de', numberFormats})

In template: {{ n(parseFloat(basket.basket.basket ?? 0), 'currency', 'de-DE') }}

Expected behavior

no errors

Reproduction

As described

System Info

tsconfig:

{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "lib": ["esnext", "dom"],
    "moduleResolution": "bundler",
    "sourceMap": false,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },

  "references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]
}


### Screenshot

_No response_

### Additional context

_No response_

### Validations

- [X] Read the [Contributing Guidelines](https://github.com/intlify/vue-i18n-next/blob/master/.github/CONTRIBUTING.md)
- [X] Read the [Documentation](https://vue-i18n.intlify.dev/)
- [X] Check that there isn't [already an issue](https://github.com/intlify/vue-i18n-next/issues) that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A open a [GitHub Discussions](https://github.com/intlify/vue-i18n-next/discussions)

apmyp1990 avatar Jun 01 '23 09:06 apmyp1990

Thank you for your reporting!

Issue template said:

Please provide a link to a repo that can reproduce the problem you ran into. A minimal reproduction is required (Why?). If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "Status: Need More Info" label. If no reproduction is provided after 5 days, it will be closed.

Could you give us your minimal reproduction please? 🙏

kazupon avatar Jun 02 '23 06:06 kazupon

I am having the same issue, except with datetimeFormats. My typescript version 5.4.4 and I am on the latest of vue-i18n:

// src/i18n.ts
import _ from 'angular-bootstrap';
import { I18n, createI18n } from 'vue-i18n';
import datetimeFormats from './date-time';


function loadLocaleMessages() {
  const messages = {};
  // Use Vite's glob import feature
  const messageModules: Record<string, unknown> = import.meta.glob('./*.vue.json', { eager: true });
  for (const path in messageModules) {
    const matched = path.match(/\/([A-Za-z0-9-_]+)\.vue.json$/);
    if (matched && matched.length > 1) {
      const locale = matched[1];
      messages[locale] = messageModules[path];
    }
  }
  return messages;
}

// Set and expose the default locale

export const defaultLocale = (window.navigator.language || 'en-us').toLowerCase();


export const supportedLocales = {
  'en-us': { name: 'English - United States' },
  'en-au': { name: 'English - Australia' },
}

// Private instance of VueI18n object

let _i18n: I18n<{}, {}, {}, string, false>


// Sets the active locale. 

const setLocale = (newLocale: string) => {
  _i18n.global.locale.value = newLocale
}

// Initializer

const setup = (options: { locale: string } = { locale: defaultLocale }) => {

  _i18n = createI18n({
    legacy: false,

    locale: options.locale,

    fallbackLocale: 'en-us',

    messages: loadLocaleMessages(),

    datetimeFormats

  });

  setLocale(options.locale);

  return _i18n;
}


// Public interface

export default {

  // Expose the VueI18n instance via a getter

  get vueI18n() {

    return _i18n

  },

  setup,

  setLocale
}

Below is the datetimeFormats:

const datetimeFormats = {
  'en-US': {
    short: {
      month: '2-digit', day: '2-digit', year: 'numeric'
    },
    long: {
      month: '2-digit', day: '2-digit', year: 'numeric',
      weekday: 'short', hour: 'numeric', minute: 'numeric'
    },
  },
  'en-AU': {
    short: {
      day: '2-digit', month: '2-digit', year: 'numeric'
    },
    long: {
      day: '2-digit', month: '2-digit', year: 'numeric',
      weekday: 'short', hour: 'numeric', minute: 'numeric'
    }
  }
}

export default datetimeFormats;

Error Message: No overload matches this call. Overload 1 of 2, '(options: I18nOptions<{ message: LocaleMessage; datetime: DateTimeFormat; number: NumberFormat; }, string, ComposerOptions<{ ...; }, ... 9 more ..., NumberFormats<...>> | VueI18nOptions<...>>, LegacyVueI18n?: any): I18n<...>', gave the following error. Type '{ 'en-US': { short: { month: string; day: string; year: string; }; long: { month: string; day: string; year: string; weekday: string; hour: string; minute: string; }; }; 'en-AU': { short: { day: string; month: string; year: string; }; long: { ...; }; }; }' is not assignable to type '{ [x: string]: DateTimeFormat; }'. Property ''en-US'' is incompatible with index signature. Type '{ short: { month: string; day: string; year: string; }; long: { month: string; day: string; year: string; weekday: string; hour: string; minute: string; }; }' is not assignable to type 'DateTimeFormat'. Property 'short' is incompatible with index signature. Type '{ month: string; day: string; year: string; }' is not assignable to type 'DateTimeFormatOptions'. Type '{ month: string; day: string; year: string; }' is not assignable to type 'SpecificDateTimeFormatOptions'. Types of property 'year' are incompatible. Type 'string' is not assignable to type 'DateTimeDigital'.

The error message is indicating that in my datetimeFormats object, I am using strings to define the year, month, day, weekday, hour, and minute properties. However, the DateTimeFormatOptions type expects these properties to be of type DateTimeDigital, which is an enum type that I don't have access to.

Note: Placing the exact same object inline works just fine, and I get no typescript errors that way.

tannert8155 avatar Apr 10 '24 15:04 tannert8155