I have a React project that I'm converting from JS to TS. An issue I'm running into is that TSX React is assuming that all properties defined in a functional component are required props.
// ComponentA.tsx
class ComponentA extends React.Component<any, any> {
render() {
/* Type '{ equalWidth: true; children: Element[]; }' is not assignable to type '{ children: any; className: any; equalWidth: any; }'.
* Property 'className' is missing in type '{ equalWidth: true; children: Element[]; }'.' */
return <ComponentB equalWidth />
}
}
and
// ComponentB.js
const ComponentB = ({ children, className, equalWidth }) => {
return (...)
}
is there a way to signal to TS that JSX component props are all optional?
One simplest option will be setting a default value for your optional props. As an example, if className
is optional you can change your ComponentB.js
to something like this.
const ComponentB = ({ children, className="", equalWidth }) => {
return (...)
}
Also if you deconstruct your props in the function body instead of the signature TS will not complain about typings.
const ComponentB = (props) => {
const { children, className, equalWidth } = props;
return (...)
}
Assuming that ComponentB.js
is going to end up as a TypeScript component:
interface ComponentBProps {
children?: ReactNode;
className?: string;
equalWidth?: boolean;
}
const ComponentB = ({ children, className, equalWidth }: ComponentBProps) => {
//
};
In the special case where all properties are optional, you could remove the ?
from each property on the interface and use Partial<ComponentBProps>
, but I guess that at least something will end up being a required prop.
If you want to keep ComponentB.js
as it is, then an alternative solution is to create a type definitions file:
import { ReactNode, StatelessComponent } from "react";
interface ComponentBProps {
children?: ReactNode
className?: string;
equalWidth?: boolean;
}
export const ComponentB: StatelessComponent<ComponentBProps>;
If you put in this the same directory as the JavaScript file and name is ComponentB.d.ts
, then you should be able to import ComponentB
in your TypeScript file.
The way I have written the definition assumes that the component is a named export, not the default, i.e. it is exported like export const ComponentB
in the .js
file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With