Search code examples
reactjstypescriptnext.jsinternationalizationi18next

Typescript i18next does not satisfy the constraint 'string | TemplateStringsArray NextJS


I'm trying to type an array of objects to be translated with i18next, but the following message occurs in variable navItems where I'm declaring the i18next to then iterate the array Type 'NavItemProps[]' does not satisfy the constraint 'string | TemplateStringsArray'. Property 'raw' is missing in type 'NavItemProps[]' but required in type 'TemplateStringsArray'

and inside the map the Property 'map' message does not exist on type 'string | object | (string | object)[]'. Property 'map' does not exist on type 'string'

I used it as a reference for typing the i18next through this link, but without success i18next: Map an array of objects in TypeScript

Component

const DesktopNav = ({hasBackground}: DesktopNavProps) => {
  const {t} = useTranslation('navbar')
  const linkColor = useColorModeValue(
    hasBackground ? 'black' : 'white',
    'gray.200'
  )
  const linkHoverColor = useColorModeValue('gray.400', 'white')
  const popoverContentBgColor = useColorModeValue('white', 'gray.800')

  const navItems = t<NavItemProps[]>('menu', {returnObjects: true})

  return (
    <C.List display={'flex'} alignItems={'center'}>
      {navItems?.map((item: NavItemProps, index: number) => (
        <C.ListItem key={index}>
          <C.Popover trigger={'hover'} placement={'bottom-start'}>
            <C.PopoverTrigger>
              <C.Link
                p={3}
                href={item.href ?? '#'}
                fontWeight={500}
                color={linkColor}
                _hover={{
                  textDecoration: 'none',
                  color: linkHoverColor,
                }}
              >
                {item.label}
              </C.Link>
            </C.PopoverTrigger>
          </C.Popover>
        </C.ListItem>
      ))}
    </C.List>
  )
}

Interface

interface NavItemProps {
  label: string
  href?: string
  subLabel?: string
  children?: Array<NavItemProps>
}

Json file translate

{
  "menu": [
    {
      "label": "jobs",
      "href": "/"
    },
    {
      "label": "about",
      "href": "/about"
    },
     {
      "label": "Blog",
      "href": "/blog"
    },
    {
      "label": "contact",
      "href": "/contact"
    }
  ]
}

Solution

  • I can't say when exactly (in which release) this happened, but apparently the order of generics for t function has changed in react-i18next types definition, compared to the link you're refering. The current definition is:

    <
        TKeys extends TFuncKey<N> | TemplateStringsArray extends infer A ? A : never,
        TDefaultResult extends TFunctionResult = string,
        TInterpolationMap extends object = StringMap
      >(
        key: TKeys | TKeys[],
        options?: TOptions<TInterpolationMap> | string,
       ): TFuncReturn<N, TKeys, TDefaultResult>;
    

    As you see, the first type refers to keys and the second one to results. So I guess you could use it like this:

    const navItems = t<string, NavItemProps[]>('menu', { returnObjects: true });