I am having an interface like this. This represents the "base button".
export interface ButtonProps {
backgroundColor?: Colors,
children?: React.ReactNode | JSX.Element,
style?: CSSProperties,
disabled?: boolean,
onClick?: () => void,
}
I now want to build ontop of that a "Text Button", a Button containing text.
interface TextButtonProps {
buttonProps?: ButtonProps,
textColor?: Colors,
}
I knwo want to extract the property backgroundColor
from ButtonProps
, using it in <TextButton />
const TextButton = ({
backgroundColor,
textColor = 'black',
textProps,
...buttonProps,
}: TextButtonProps) => {
return (
...
)
Is there a way to make backgroundColor
available to <TextButton />
, without explicitly naming it again in the TextButtonProps
? I could do it like this
interface TextButtonProps {
backgroundColor?: Colors,
buttonProps?: ButtonProps,
textColor?: Colors,
}
But I would repeat myself, because ButtonProps
contains already backgroundColor
.
3
Answers
If you want to declare a type that has additional properties, you can use an intersection:
You could keep your types as-is and pass the properties down to
Button
:If you need to use, for example,
ButtonProps.backgroundColor
inside<TextButton>
then you’d need to write something like this<Text foreground={textColor} background={buttonProps?.backgroundColor}>
. I, personally, findTextButtonProps.buttonProps
a bit confusing: think about the caller:Truly confusing.
As a note: you can pick a property from a type:
But it’s NOT what I’d do here, I’d simply extend the
ButtonProps
interface with the additional properties:Your component will then be:
An extra note: you do not need to declare
children
if you useReact.FC
(I strongly suggest to always do it). Note that types for React 18 change a bit so you might need to useReact.FC<React.PropsWithChildren<ButtonProps>>
.Another one: remember that
type T = { ... } & V
is NOT the same asinterface T extends V { ... }
(even if, in most cases, you probably do not care about the difference).Try this without creating an extra type definition:
TextButtonProps & TextButtonProps[keyof TextButtonProps] as type, it should take the nested types too