I'm poking around with exploring a typescript pattern and I'm not sure if it can be done.
essentially, in my React component I have the following interface:
interface IPaper {
className?: string;
children: React.ReactNode;
elevation?: 'low' | 'medium' | 'high';
}
while the above example is fine, I want to explore something smarter and easier to maintain. Specifically, using the keys currently found in the ThemeParameters
example shown below:
interface ThemeParameters extends StorybookIntegration {
...
elevation: {
low: string;
medium: string;
high: string;
};
...
}
In practice my component would look something like the example below with the component's elevation
property being coupled to whatever the elevation setup is like in my ThemeParameters
. That way, if I ever modify my theme it will be automatically captured by the interface on the component.
interface IPaper {
className?: string;
children: React.ReactNode;
elevation?: ThemeParameters['elevation'];
}
const Paper = ({ className, children, ...props }: IPaper): JSX.Element => (
<Wrapper className={className} elevation="low" {...props}>
{children}
</Wrapper>
);
const Wrapper = styled.div<{ elevation: string }>`
box-shadow: ${({ theme, elevation }) => theme.elevation[elevation]};
`;
Unfortunately, this isnt exactly working. Any clever ideas with how I can set this up using typescript?
example using the suggestion from the best answer below.
ThemeParameters['elevation']
is this type:
{
low: string;
medium: string;
high: string;
}
So you want the keys of that of object. That's what keyof
is for:
keyof ThemeParameters['elevation']
Which is this type:
'low' | 'medium' | 'high'