Consider this use case: I have a React functional component that I'd like to implement with the props being destructured (for consistency with all the other components).
This is a checkbox which has two possible roles. If it is associated with the full amount of data, it can be interacted with, and if it is associated with limited data, it will display a name, but the elements cannot be interacted with.
This can be simply implemented by the use of two independent components, and I may just go with that approach, but I wonder about the extent to which it is possible to extend and flesh out an existing component in code in this way.
So, i'm starting with a checkbox component that takes this type for props:
export interface CheckboxProps {
checked: boolean;
id: string;
disabled?: boolean;
disabledTooltipLabel?: string;
onChange: VoidFunction;
labelOrientation?: CheckboxLabelOrientation;
label?: string;
className?: string;
}
With this destructuring for the props to start off the function component definition:
export const Checkbox: React.FunctionComponent<CheckboxProps> = ({
checked,
disabled,
disabledTooltipLabel,
id,
onChange,
labelOrientation = "left",
label = "",
className,
}) => {
...
and I'm hoping to extend this with minimal refactoring to allow me to feed in a much simplified input consisting solely of label, e.g. with a tweaked type. However now if I try to actually use this, the destructuring is impossible:
export interface CheckboxProps {
checked: boolean;
id: string;
disabled?: boolean;
disabledTooltipLabel?: string;
onChange: VoidFunction;
labelOrientation?: CheckboxLabelOrientation;
label?: string;
className?: string;
}
type CheckboxBarebones = Pick<CheckboxProps, "label">;
export const Checkbox: React.FunctionComponent<
CheckboxBarebones | CheckboxProps
> = (props) => {
const { label } = props;
if ("checked" in props) {
var {
checked,
disabled,
disabledTooltipLabel,
id,
onChange,
labelOrientation = "left",
className,
} = props;
}
...
This might work in theory, but I get vars-on-top
and a torrent of block-scoped-var
eslint errors. Is there any kind of "lite" destructuring I could do? Even if I manually pull values out of the props, how could I even go about doing it cleanly if I want to use const
?
Since this is so completely horrific, I kept working and came up with:
export const Checkbox: React.FunctionComponent<
Pick<CheckboxProps, "label"> | CheckboxProps
> = (props) => {
const {
label,
checked,
disabled,
disabledTooltipLabel,
id,
onChange,
labelOrientation = "left",
className,
} = props as Partial<CheckboxProps>;
...
This seems like an improvement, but it still has a type cast in it and cannot be directly destructured in arrow function parameter. Is there a way to avoid it? I like how this preserves a useful type contract for the function component's props, which is the important thing here.
You can keep the desired props type for consumers, but in the implementation define it as partial without casting:
const Checkbox: React.FC<Pick<CheckboxProps, "label"> | CheckboxProps> = ({
label,
checked,
disabled,
disabledTooltipLabel,
id,
onChange,
labelOrientation = "left",
className,
}: Partial<CheckboxProps>) => {
return <>...</>;
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments