import { ReactElement } from 'react'
type IModalOption = {
tag: 'IModalOption'
}
interface Props {
isOpen: boolean;
type: 'basic';
options?: IModalOption;
}
type Union<T extends string> = T extends string ? Record<T, ReactElement> : never
type IModalProps = Props & Union<'content' | 'children'>
// error, there are no 'content' and/or 'children'
const props: IModalProps = {
isOpen: true,
type: 'basic',
options: {
tag: 'IModalOption'
},
}
// ok
const props2: IModalProps = {
isOpen: true,
type: 'basic',
options: {
tag: 'IModalOption'
},
content: null as any as ReactElement
}
// ok
const props3: IModalProps = {
isOpen: true,
type: 'basic',
options: {
tag: 'IModalOption'
},
children: null as any as ReactElement
}
// ok
const props4: IModalProps = {
isOpen: true,
type: 'basic',
options: {
tag: 'IModalOption'
},
children: null as any as ReactElement,
content: null as any as ReactElement
}
Union utility type distributes content | children.
It means that it is applied to each union. Union<'content' | 'children'> returns Record<'content, ReactElement> | Record<'children, ReactElement>.
In order to achieve desired behavior, you just need to merge base props with union:
type IModalProps = Props & Union<'content' | 'children'>
Playground