Уловка для FormattedMessage и formatMessage от react-intl

TL; DR; путем создания оболочки для FormattedMessage компонента и formatMessage функции r eact-intl, вы можете добавить типобезопасность, чтобы допускались только допустимые идентификаторы сообщений перевода. . Вот пример репо и немного сути.

С r eact-intl вы можете переводить сообщения с помощью компонента FormattedMessage или с помощью функции formatMessage. В любом случае вы должны указать id для сообщения, которое обычно имеет тип string | number.

Это означает, что вы можете передать любую строку или любое число, даже если сообщения для этого идентификатора не существует ...

Но, зная все возможные идентификаторы сообщений, мы можем добавить дополнительную безопасность типов в id prop / argument, чтобы он принимал только те значения, которые действительно существуют в наших файлах перевода. В качестве дополнительного преимущества мы также получим IntelliSense из нашей IDE при вводе значения аргумента (как и следовало ожидать при использовании TypeScript).

Из типичного файла JSON, содержащего сообщения перевода:

// en.json
{
  "helloWorld": "Hello world!",
  "goodbye: "Goodbye"
}

мы можем создать объединение всех идентификаторов сообщений:

Типобезопасный компонент FormattedMessage

Для каждого компонента / функции перевода мы можем написать легкую оболочку, которая улучшит базовую функцию react-intl, добавив более конкретную типизацию к аргументу id, оставив все остальные типы такими же.

Для компонента FormattedMessage это выглядит так:

Это выглядит сложно, но в основном это связано с типом FormattedMessageProps, который мы создали на основе свойств исходного компонента. Чтобы убедиться, что мы точно соответствуем исходным типам опор, мы импортировали их прямо из react-intl/src/components/message, а затем улучшили тип id.

Если вы используете компонент FormattedMessage относительно просто, вы можете просто определить полный тип свойств самостоятельно, и этого, вероятно, будет достаточно для удовлетворения ваших потребностей:

Типобезопасная функция formatMessage

Обеспечение типобезопасной оболочки для функции formatMessage требует немного больше работы, потому что сама функция возвращается из ловушки useIntl:

Здесь мы улучшаем тип аргумента descriptor, чтобы параметр id использовал наш новый тип IntlMessageKeys. Чтобы гарантировать, что все остальные аргументы остаются такими же, мы используем служебный тип TypeScript Parameters для извлечения типов аргументов из исходного типа функции и доступа к ним один за другим.

Использование новых функций

Поскольку мы убедились, что сигнатуры функций не изменились, мы можем использовать наши новые FormattedMessage и formatMessage точно так же, как и исходные. Предполагая, что мы определили их оба в одном файле, мы можем просто заменить оператор импорта с react-intl на наш новый локальный файл:

И как только мы это сделаем, преимущества этой работы станут очевидны:

Благодаря нашему новому компоненту и функции перевода принимаются только действительные идентификаторы сообщений, и наша IDE обязательно нам поможет. Больше нет риска орфографических ошибок и случайного использования несуществующих идентификаторов сообщений. TypeScript, как и следовало ожидать.