Typescript error when using variables in Trans component
🐛 Bug Report
Typescript throws when using variable in Trans component. Maybe a bit of an edge case, but when using a custom component that expects string as children within Trans and the child to this component should include a variable Typescript throws an error. Also it is impossible to ignore TS in this situation.
To Reproduce
Note that this is a minimal reproduction (e.g. i18next is not fully set up).
One of the conditions for this bug is that you have the child in a separate line. If they would be in one line, you could add a `{/* @ts-ignore */} before hand. However it is not working when the code is in multiple lines.
Expected behavior
TS doesn't throw or at least there is a way to ignore it.
outside of your StringWrapper it works, right? https://codesandbox.io/s/mutable-bash-6gdqy2?file=/src/App.tsx:323-348
@adrai do you mean if you move the variable to a different position? Yes, that works.
But that is not a viable solution, if the variable needs to be inside the string of StringWrapper.
I'm not a TypeScript user, but if it works like this:
<Trans>
<StringWrapper className="my-class">
Your count
</StringWrapper>
{{ amount: data.length }} has been counted
</Trans>
it may be your StringWrapper component is doing something that is causing the problem.
This solution doesn't answer the requirements (see above). Also that component doesn't do much (see in the example attached).
Hey @eszthoff, that's happening because your StringWrapper doesn't accept ReactNode just string.
You can simply remove the children prop from StringWrapper, and it should work fine, React.FC already includes a children.
Thank for your work and the suggestions.
Unfortunately changing the children type will also not fulfil the requirements. Even in the current (contrived) example that will allow incorrect children to be passed. E.g. <div>text</div> that would result in incorrect HTML such as <span><div>text</div></span>.
I think there are several real world scenarios when you want to have a strong type checking:
-
StringWrapperis part of a library that you expect others to use -
StingWrapperis used by a large amount of developers in your company in different context whereTransis only one use case.
I played around a bit more with the problem and found a solution that I think is acceptable. Posting it here, in case it helps others. The solution is not perfect, but at least it allows one to add a @ts-ignore comment.
If the TS declaration changed from using React.FC to just declaring the props, it moves to error message one line higher, hence allowing adding comments to the line above that. The resulting code would look something like that:
const StringWrapper = (props: Props) => {...}
If needed the return type can be also added in the usual way.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I'm experiencing something similar:
const title = `${title} something`
return (
<Trans i18nKey="myKey">
Edit <span style={{color: '#40a9ff'}}>{{title}}</span>
</Trans>
)
// where myKey=Edit Entity<1>{{title}}</1>
yields:
TS2322: Type '{ title: string; }' is not assignable to type 'ReactNode'. Object literal may only specify known properties, and 'title' does not exist in type 'ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal'.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Problem still exists. Maybe there's a workaround for default components like span?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Problem still exists...
Everyone who is still facing this problem, please set allowObjectInHTMLChildren to true in your react-i18next type declaration file. You can follow the instructions here to learn how to create a type declaration file, it should look similar to this one:
import "react-i18next";
...
declare module "react-i18next" {
interface CustomTypeOptions {
allowObjectInHTMLChildren: true, // This property should be true
defaultNS: "ns1";
resources: {
ns1: typeof ...;
};
}
}
If the error still persists, please share a minimalistic version of your app (using the Trans component), and I'll help you.
As far as I could see, @eszthoff issue is different from others as she can't change the children Props, if you can't change the children props to React.ReactNode or string | Record<string, unknown>;, please explain why and I'll try to help you.
@pedrodurek Setting allowObjectInHTMLChildren to true works for me. Thanks.
What is the reason why it is not true by default? Are there any disadvantages?
@pedrodurek Setting
allowObjectInHTMLChildrentotrueworks for me. Thanks.What is the reason why it is not true by default? Are there any disadvantages?
Wouldn't that suppress typescript errors on any children prop?
Objects are not valid JSX children, meaning that outside Trans components I'd expect it to crash the runtime?
@BrooceLR I tested this, allowObjectInHTMLChildren works like disabling the TypeScript warning globally. It suppresses warnings in all JSX. So this is not a good solution.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I found an solution for this, you can pass values to Trans component like this:
<Trans values={{ amount: data.length }}>
<StringWrapper className="my-class">
Your count
</StringWrapper>
{data.length} has been counted
</Trans>