Omit<Typography, 'color'> does not work as intended

Viewed 136

So this example code:

import { Typography, TypographyProps } from '@material-ui/core';
import { palette, PaletteProps } from '@material-ui/system';
import styled from '@emotion/styled';

type TextProps = Omit<TypographyProps, 'color'> & PaletteProps;

export const Text = styled(Typography)<TextProps>`
  ${palette}
`;

Does not work as you'd expect. The idea here is: color is typed any in PaletteProps, but it is typed "inherit" | "primary" | "secondary" | "textPrimary" | ... | undefined in TypographyProps. What I wanted to do is overwrite the color prop, so I could use @material-ui/system's color, instead of Typography's color prop.

Maybe I'm doing something wrong or maybe there's something I haven't accounted for. Here's a CodeSandbox URL with the error being reproduced:

https://codesandbox.io/s/b36zs?file=/src/App.tsx (hover the <Text ...> component for the Typescript error - it doesn't prevent the compilation there, but locally that does not work at all).

What am I missing here?

2 Answers

According to your answer (André Castelo), you can improve this piece of code by making an alias of the original material UI component and type, because the component TypographyWithoutColor is confusing due to it's using the color prop from PaletteProps. Also your overrides will be cleaner since you don't need to create new names for components or types you need to override or enhance.

So it's how it would look like:

import { Typography as MuiTypography, TypographyProps as MuiTypographyProps } from '@material-ui/core';
import { palette, PaletteProps } from '@material-ui/system';
import styled from '@emotion/styled';

export type TypographyProps = PaletteProps & Omit<MuiTypographyProps, 'color'>;

export const Typography = styled(({ color, ...props }: TypographyProps) => (
  <MuiTypography {...props} />
))<TypographyProps>`
  ${palette}
`;

So Emile's comment gave me an idea, and I changed the code to

import { Typography, TypographyProps } from '@material-ui/core';
import { palette, PaletteProps } from '@material-ui/system';
import styled from '@emotion/styled';

type TextProps = Omit<TypographyProps, 'color'> & PaletteProps;

const TypographyWithoutColor = ({ color, ...props }: TextProps) => (
  <Typography {...props} />
);

export const Text = styled(TypographyWithoutColor)<TextProps>`
  ${palette}
`;
Related