Suppose there is a Modal component that contains two variants: title
and non-title
.
When the variant is title
, there is an prop named title, when the variant is non-title
, there is no such prop.
If you simply define the Modal props as follows:
type ModalProps = {
variant: 'title' | 'non-title';
title?: string;
};
typescript does not recognize when a title should be absent. That is, even if we pass the variant ‘non-title’ and also pass in the title, typescript will not give the expected warning.
You need to define ModalProps
as Discriminated Unions:
type ModalProps = {
variant: 'title';
title: string;
} | {
variant: 'non-title';
};
Such a definition of ModalProps
applies different types when the variant is passed as title and non-title, so that typescript knows what props are available for a given variant, and if title is passed along with the variant non-title, typescript will give a warns you about it.
Add props across discriminated unions
Suppose we need to add a generic required prop buttonColor
to the above ModalProps
, what should we do? The easiest form to think of is to add the definition of that prop to each union type separately:
type ModalProps = {
variant: 'title';
title: string;
buttonColor: string;
} | {
variant: 'non-title';
buttonColor: string;
};
This does solve the problem, but it’s not convenient enough. If there are more variants, you need to add, delete, and change them one by one when maintaining these generic props.
So is there a more efficient and elegant way to do this type definition processing? The answer is yes, simply wrap the original union type in parentheses and then unite a new type:
type ModalProps = ({
variant: 'title';
title: string;
} | {
variant: 'non-title';
}) & {
buttonColor:string;
};
Or handle it this way to improve readability:
type ModalVariantProps = {
variant: 'title';
title: string;
} | {
variant: 'non-title';
};
type ModalProps = ModalVariantProps & {
buttonColor:string;
};
In this way, the type definition following the & sign is applied to each variant type separately, and modifications made inside this type definition are applied to all variants.