Using i18next to efficiently map an array of objects in TypeScript

I am currently converting a React project to TypeScript and using Packages like Next.js, next-i18next, and styled-components.

EDIT:

The information provided here may be outdated due to current versions of next-i18next.

Please check out: Typescript i18next does not satisfy the constraint 'string | TemplateStringsArray NextJS

For a quick example, consider the following code snippet:

{t<string, ItemProps[]>('document.items', {returnObjects: true}).map(({ name, description, index }) => (
  <li key={index}>
    <strong dangerouslySetInnerHTML={{__html: name}} />
    <Paragraph dangerouslySetInnerHTML={{__html: description}} />
  </li>
   )
)}

You can also view a working solution in this codesandbox.

Original Question:

In my language json file, I used an array of objects as shown below:

{
  "websites":
  [
    {
      "slug": "website-a",
      "name": "Website A"
    },
    {
      "slug": "website-b",
      "name": "Website B"
    }
  ]
}

To list all websites using i18next's { t }:

t('websites', {returnObjects: true}).map(({slug, name}) => ( ... ))

When using TypeScript, it showed an error for map:

Property 'map' does not exist on type 'string'.

To address this issue, I defined types and modified the code:

type websiteProps = {
  map: Function;
};

type itemProps = {
  slug: string;
  name: string;
};

t<websiteProps>('websites', {returnObjects: true}).map(({slug, name}: itemProps) => ( ... ))

This solution resolved the issue but I am open to suggestions for better alternatives. Any feedback is appreciated!

Thank you!

Answer №1

@cherryblossom's response is spot on - I am sharing a new answer to offer additional details.

Below is the defined type for the i18n t function (utilized in your code):

  <
    TResult extends TFunctionResult = string,
    TKeys extends TFunctionKeys = string,
    TInterpolationMap extends object = StringMap
  >(
    key: TKeys | TKeys[],
    options?: TOptions<TInterpolationMap> | string,
  ): TResult;

This function is generic and can accept TResult, Tkeys, and TInterpolationMap as parameters. When not explicitly specified, TResult defaults to "string," which is why the .map function throws an error.

If you expect an array of items as the output, make sure to define the TResult type parameter like @cherryblossom mentioned:

t<itemProps[]>('websites', {returnObjects: true}).map(...)

It's always helpful to refer to the type definitions of the libraries you are utilizing when dealing with issues like this. Make it a habit to consult them initially in such situations.

Answer №2

While I'm not an expert on i18, you might want to consider using the following code snippet:

t<itemProps[]>('websites', {returnObjects: true}).map(({slug, name}: itemProps) => ( ... ))

This code informs TypeScript that t will be returning an array of itemProps.


I was curious if simply removing underlines for .map would work.

It's generally not recommended to ignore TypeScript compiler errors. However, in exceptional cases, you can utilize // @ts-ignore above the line of code to suppress the error.

Answer №3

Since the latest version of i18next (version 23), a change has been made where you now need to provide 3 type arguments when using the t function. The first argument is for the key type, the second is for any options you want to pass, and the third is for the return type.

An example of how you would write this is:

t<'websites', { returnObjects: true }, itemProps[]>('websites', {returnObjects: true}).map(({slug, name}: itemProps) => ( ... ))

This new approach can be quite verbose, so you may consider creating your own reusable function to streamline this process and reduce boilerplate code.

For more information, visit: https://github.com/i18next/i18next/issues/2151

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Troubleshooting: Issues with accessing Angular/Typescript Class Getter property

I have a class defined as follows: export class Story { id: number; title: string; storyText: string; utcDate: string; get displayDate(): string { const today = new Date(); const postDate = new Date(this.utcDate); ...

Using the Ajax method from a separate class in TypeScript: A step-by-step guide

Recently, I started learning about typescript and ajax. One of the challenges I encountered was while creating a method in typescript for making ajax calls that can be used across classes: myFunc(value: string): JQueryPromise<any> { var dfd = $. ...

Disabling specific time slots in the mat select functionality

I have a scenario where I need to display time slots at 30-minute intervals using Mat Select. export const TIME=["12:00 AM","12:30 AM","01:00 AM","01:30 AM","02:00 AM","02:30 AM","03:00 AM&qu ...

standards for matching patterns (such as .gitignore)

Throughout my experience, I have utilized various tools designed to search a codebase for specific files and then carry out operations on those files. One example is test libraries that identify all the necessary files for execution. Another common tool is ...

initiate file transfer

I am currently developing a web application using NextJS with TRPC. Within the app, there is a form that requires users to select a file. My goal is to pass this file through a TRPC call to handle all file-related logic on the backend rather than the front ...

Exploring ways to retrieve the chosen value from a personalized dropdown menu in React?

I'm currently utilizing styled components along with typescript to retrieve the selected option value of a customized dropdown. However, I am encountering an issue where the value does not update as expected. Interestingly, when I remove the opacity f ...

Angular 7 navigation successfully updates the URL, but fails to load the corresponding component

Despite exhausting all other options, I am still facing a persistent issue: when trying to navigate to a different component, the URL changes but the destination component fails to load. Explanation: Upon entering the App, the user is directed to either ...

I am developing a JWT authentication and authorization service for my Angular application. However, I am running into issues when trying to implement observables

I have created a user class and required interfaces as outlined below: user.ts import { Role } from '../auth/auth.enum' export interface IUser { _id: string email: string name: IName picture: string role: Role | string userStatus: b ...

The NodeJS application experiences a crash if incorrect parameters are provided to the API

Currently, I have built a CRUD API using TypeScript with Node.js, Express, and MongoDB. My goal is to ensure that the API functions correctly when the correct parameters are sent through a POST request. However, if incorrect parameters are passed, the Node ...

Navigating Routes with Router in Angular 7: A Step-by-Step Guide

Within my sidebar navigation component, the sidebar.component.html file is structured as follows: <nav class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top" id="sideNav"> <a class="navbar-brand" href="#page-top"> <span cl ...

Is there a way to nest child components in Next.js similar to how it's done in React?

Exploring nested children components in Next.js as a React JS developer. In React, I used the outlet to nest child components, but I am unsure how to achieve this in Next.js. Folder Structure: https://example.com/folder-structure.png Index.js: https:// ...

Utilizing "regression-js" within an Angular 2 project: A comprehensive guide

I have integrated the Regression npm module https://www.npmjs.com/package/regression into my Angular 2 application to utilize the Linear Regression functionality. I installed the package using "npm install regression". However, I encountered errors while a ...

Challenge with using the React useEffect hook

Incorporating the React useEffect hook into my code has been a bit challenging. Here is how I am attempting to use it: function App() { React.useEffect(() => { console.log('effect working') }, []) return ( <div className=" ...

Prohibit the Use of Indexable Types in TypeScript

I have been trying to locate a tslint rule in the tslint.yml file that can identify and flag any usage of Indexable Types (such as { [key: string] : string }) in favor of TypeScript Records (e.g. Record<string, string>). However, I haven't had a ...

Ways to resolve the issue "How to address the React hook error stating "React Hook 'React.useState' is being called conditionally"?"

I encountered an issue while attempting to build my next.js project. How can I resolve it? It seems that the error is related to using hooks conditionally. ./src/lib/session.js 6:29 Error: React Hook "React.useState" is called conditionally. R ...

Encountering an unanticipated runtime error in Next.JS upon page refresh

My current project involves implementing a dynamic ID on a web page, utilizing Tanstack React-Query for data querying. However, I have encountered an issue where refreshing the page with an ID in the URL triggers the following error message: Unhandled Run ...

What are the differences between Modules and Typings in Typescript?

I have been searching far and wide for information on the variances between modules and typings in TypeScript, but I'm still struggling to grasp the concept. As a newcomer to TypeScript, could someone please provide a concise explanation of these diff ...

What is the best way to manage routes within the NEXTJS api?

Can someone clarify the correct approach or explain the difference between these two methods? 1 create a /api/pages export default function handler(req, res) { if (req.method === 'POST') { // Process a POST request } else { // Handle ...

It appears that Jest is having trouble comprehending the concept of "import type"

We've just completed a major update to our monorepository, bringing it up to date with the following versions: Nx 14.3.6 Angular 14.0.3 Jest 28.1.1 TypeScript 4.7.4 Although the compilation process went smoothly after the upgrade, we encountered num ...

Encountered an HttpErrorResponse while trying to access the API endpoint

I am encountering an issue when trying to update and insert data with a single post request. Below is my API code: Here is the service code: This section includes the function calling code: Additionally, this is the model being used The API C# model c ...