Search code examples
reactjstypescriptstyled-components

How to destructure a typescript interface and use it in another interface?


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?


SOLUTION

example using the suggestion from the best answer below.

enter image description here


Solution

  • 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'
    

    Playground