Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typing error with React 18 #1817

Closed
azuken opened this issue May 2, 2022 · 18 comments
Closed

Typing error with React 18 #1817

azuken opened this issue May 2, 2022 · 18 comments

Comments

@azuken
Copy link

azuken commented May 2, 2022

Describe the bug

NextJS build is failing with React 18 and usage of component.

Occurs in next-i18next version

11.0.0

Steps to reproduce

info  - Loaded env from /.env
Failed to compile.

./src/components/Component.tsx:179:56
Type error: Type '{ freeDays: number; }' is not assignable to type 'ReactNode'.
  Object literal may only specify known properties, and 'freeDays' does not exist in type 'ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal'.

  177 |                     <Trans i18nKey="subscribe.freeDays">
  178 |                       You get
> 179 |                       <span className="family-bold">{{ freeDays }}</span>
      |                                                        ^
  180 |                       &nbsp;starting today
  181 |                     </Trans>
  182 |                   </p>
info  - Checking validity of types .%   

Expected behaviour

No typing errors when using variables in Trans component

OS (please complete the following information)

  • Device: MBP 2019 16
  • Browser: Chrome 100.0.4896.127
@isaachinman
Copy link
Contributor

Typings for the Trans component come from react-i18next, not this package. Please open an issue there.

@azuken
Copy link
Author

azuken commented May 2, 2022

For tracking : i18next/react-i18next#1483

@adrai
Copy link
Member

adrai commented May 2, 2022

@azuken would such a TypeScript option like allowObjectInHTMLChildren work for you?
Please comment here: i18next/react-i18next#1483
And maybe check also this PR: i18next/react-i18next#1492
@isaachinman if you have some inputs regarding that, let us know...

@azuken
Copy link
Author

azuken commented Jul 12, 2022

@adrai Since it seems that there is no better solution, yeah it would be great to have this in this package.

@adrai
Copy link
Member

adrai commented Jul 12, 2022

@adrai Since it seems that there is no better solution, yeah it would be great to have this in this package.

fyi: allowObjectInHTMLChildren was already introduced in react-i18next, so you might just update your dependencies

@azuken
Copy link
Author

azuken commented Jul 12, 2022

@adrai this is just what I've done and I have no such option in Trans component. I'm importing component from next-i18next, not react-i18next

@adrai
Copy link
Member

adrai commented Jul 12, 2022

@adrai this is just what I've done and I have no such option in Trans component. I'm importing component from next-i18next, not react-i18next

you might need to delete your node_modules folder... react-i18next is a dependency of next-i18next

@azuken
Copy link
Author

azuken commented Jul 12, 2022

This is what I'm doing everytime I update packages.
I've just removed yarn lock in case of, same behaviour :

info  - Linting and checking validity of types .Failed to compile.

./src/components/Coupon/Confirm.tsx:186:56
Type error: Type '{ freeDays: number; }' is not assignable to type 'ReactNode'.
  Object literal may only specify known properties, and 'freeDays' does not exist in type 'ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal'.

  184 |                     <Trans i18nKey="subscribe.freeDays" allowObjectInHTMLChildren={true}>
  185 |                       You get
> 186 |                       <span className="family-bold">{{ freeDays }}</span>
      |                                                        ^
  187 |                       &nbsp;starting today
  188 |                     </Trans>
  189 |                   </p>

> Build error occurred

My code :

<Trans i18nKey="subscribe.freeDays" allowObjectInHTMLChildren={true}>
  You get
  <span className="family-bold">{{ freeDays }}</span>
  &nbsp;starting today
</Trans>

@adrai
Copy link
Member

adrai commented Jul 12, 2022

This is what I'm doing everytime I update packages. I've just removed yarn lock in case of, same behaviour :

info  - Linting and checking validity of types .Failed to compile.

./src/components/Coupon/Confirm.tsx:186:56
Type error: Type '{ freeDays: number; }' is not assignable to type 'ReactNode'.
  Object literal may only specify known properties, and 'freeDays' does not exist in type 'ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal'.

  184 |                     <Trans i18nKey="subscribe.freeDays" allowObjectInHTMLChildren={true}>
  185 |                       You get
> 186 |                       <span className="family-bold">{{ freeDays }}</span>
      |                                                        ^
  187 |                       &nbsp;starting today
  188 |                     </Trans>
  189 |                   </p>

> Build error occurred

My code :

<Trans i18nKey="subscribe.freeDays" allowObjectInHTMLChildren={true}>
  You get
  <span className="family-bold">{{ freeDays }}</span>
  &nbsp;starting today
</Trans>

I'm not a TypeScrirpt user, but allowObjectInHTMLChildren is not a Trans prop, but should probably be used like this: https://github.com/i18next/react-i18next/blob/master/ts4.1/index.d.ts#L29

@pedrodurek correct me if I'm wrong

@pedrodurek
Copy link
Member

yeah @adrai, that's correct! allowObjectInHTMLChildren will allow all html elements to accept object as children.

@azuken
Copy link
Author

azuken commented Jul 18, 2022

@adrai I see no usage example in your link, just interface. I do not understand how to implement this option.

@adrai
Copy link
Member

adrai commented Jul 18, 2022

Do you mean this? https://react.i18next.com/latest/typescript

@azuken
Copy link
Author

azuken commented Jul 18, 2022

Ok, I didn't understand that it was an i18n configuration.

But still not working.

My configuration :

next-i18next.config.js

const intervalPlural = require('i18next-intervalplural-postprocessor');

module.exports = {
  i18n: {
    defaultNS: 'translation',
    serializeConfig: false,
    fallbackLng: 'fr-FR',
    locales: ['fr-FR', 'en-US', 'es-ES', 'de-DE', 'catchAll'],
    defaultLocale: 'catchAll',
    interpolation: {
      escapeValue: false
    },
    react: {
      transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p', 'u']
    },
    use: [intervalPlural],
    allowObjectInHTMLChildren: true
  }
};

Error :

Type error: Type '{ freeDays: number; }' is not assignable to type 'ReactI18NextChild | Iterable<ReactI18NextChild>'.
  Object literal may only specify known properties, and 'freeDays' does not exist in type 'ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal | Iterable<ReactI18NextChild>'.

  184 |                     <Trans i18nKey="subscribe.freeDays">
  185 |                       You get
> 186 |                       <span className="family-bold">{{ freeDays }}</span>
      |                                                        ^
  187 |                       &nbsp;starting today
  188 |                     </Trans>
  189 |                   </p>

> Build error occurred

EDIT :
My js configuration above is indeed imported in next.config.js.

@adrai
Copy link
Member

adrai commented Jul 18, 2022

@pedrodurek can you help...? There is probably a bit of confusion.

@pedrodurek
Copy link
Member

@azuken Ohh sorry, only react-i18next is supporting it right now, I'd recommend to change the react types manually then.
1 - Create a react.d.ts file in your src path.
2 - Add the following code to the file:

import React from 'react';
type ReactI18NextChild = React.ReactNode | Record<string, unknown>;

declare module 'react' {
  interface HTMLAttributes<T> {
    children?: ReactI18NextChild | Iterable<ReactI18NextChild>;
  }
}

@azuken
Copy link
Author

azuken commented Jul 19, 2022

@pedrodurek Unfortunately, still not working !

It overrides React own definition types, so I've got an error like :

Type error: Module '"react"' has no exported member 'useEffect'.

  3 | import Head from 'next/head';
  4 | import Link from 'next/link';
> 5 | import React, { useEffect } from 'react';
    |                 ^
  6 | import StaticPageManager from 'src/containers/StaticPageManager';
  7 | import { captureError } from 'src/utils/sentry/error-handler';
  8 | import NoHeaderFooterLayout from '../Layout/NoHeaderFooter';

I've searched and tried to fix this, changing d.ts file :

import React from 'react';

type ReactI18NextChild = React.ReactNode | Record<string, unknown>;

declare global {
  namespace React {
    interface HTMLAttributes<T> {
      children?: ReactI18NextChild | Iterable<ReactI18NextChild>;
    }
  }
}

Declare file into tsconfig.json (both include and typeRoots properties), changing file name but it continues to override base types.

@pedrodurek
Copy link
Member

Hey @azuken, when you import react in the type declaration file it should import all original types as well. I created a project from scratch here and it worked https://github.com/pedrodurek/react-merge-type.

@azuken
Copy link
Author

azuken commented Jul 21, 2022

Ok it's working if I move definition file into src folder, instead in root!

Thank you for your help, is there any ticket, issue, MR opened to track when this will be implemented in this library ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants