Ошибка «динамического» импорта даты-библиотеки fns/локали — машинопись, приводящая к ошибке при попытке импорта

#javascript #typescript #import #locale #date-fns

Вопрос:

У меня есть приложение, которое получает список поддерживаемых языков от серверной части в качестве следующего ответа:

 {locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'arAR'}]}
 

Я хочу использовать библиотеку date-fn для обработки форматирования даты, но мне нужно импортировать всю дату-fn/языковой стандарт, так как я не могу заранее знать, какой языковой стандарт потребуется:

 import * as dateFnsLocales from 'date-fns/locale';
 

Проблема в том, что некоторые локали имеют другой формат кода (например, поддержка немецкого языка включена, когда внутренний ответ содержит код: «deDE», но соответствующий пакет date-fns-это просто «de». С другой стороны, пакет date-fns для английского языка-это «enUS», а не просто «en».

Простым решением имхо было бы справиться с этим с помощью какого-нибудь объединяющего оператора. Пример следующий:

 import * as dateFnsLocales from 'date-fns/locale';

const supportedLocales = {locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'plPL'}]}
const newArrayWithSupportedLocales = supportedLocales.locales.map((locale) => ({
        ...locale,
        dateFnsLocale: (dateFnsLocales[locale.code] || dateFnsLocales[locale.code.substring(0,2)]),
      }));
 

К сожалению, я получаю ошибку машинописи:
No index signature with a parameter of type 'string' was found on type 'typeof import("date-fns/locale")'. TS7053

Даже если я жестко закодирую попытку так:

 dateFnsLocale: dateFnsLocales['plPL'.substring(0,2)]
 

он завершается с той же ошибкой, хотя это:

 dateFnsLocale: dateFnsLocales['pl']
 

работает просто отлично.

Ответ №1:

Вот код, который я использую для динамического поиска с использованием Localization объекта Expo.

 import * as Localization from 'expo-localization';
import * as Locales from 'date-fns/locale';
import { Locale } from 'date-fns';

/**
 * Looks up a date-fns locale from the Expo localization object.  This falls back to `en-US`
 * @param localization Expo Localization object containing the locale and region.
 * @returns date-fns locale.
 */
export function getDateFnsLocale({ locale, region }: Pick<typeof Localization, 'locale'|'region'>) : Locale {
  return (
    Locales[locale.substring(0, 2)   region] ?? Locales[locale.substring(0, 2)] ?? Locales.enUS
  );
}
 

Вот тест

 import { enUS, fr, frCA } from 'date-fns/locale';

describe('date-fns locale lookup', () => {
  it('shound find fr', () => {
    expect(getDateFnsLocale({ locale: 'fr', region: null })).toBe(fr);
  });
  it('shound find fr-CA', () => {
    expect(getDateFnsLocale({ locale: 'fr-CA', region: 'CA' })).toBe(frCA);
  });
  it('shound not find zz-ZZ', () => {
    expect(getDateFnsLocale({ locale: 'zz-ZZ', region: 'ZZ' })).toBe(enUS);
  });
});
 

Комментарии:

1. Спасибо за ответ и полезные тесты!