The point of this Type is to allow user to pass in either data, color, hasColor or data, info, hasInfo. Not any other combination.
type Props = {
data: string;
} & (
| {
info?: string;
hasInfo?: boolean;
color?: never;
hasColor?: never;
}
| {
info?: never;
hasInfo?: never;
color?: string;
hasColor?: boolean;
}
);
function foo(props: Props) {
console.log("bar");
}
foo({ data: "hello", info: "hello", hasInfo: true }); <----- TypeScript is happy
foo({ data: "hello", info: "hello", hasColor: true }); <----- TypeScript gives Error
Is there a cleaner way to implement this behavior using generics?
I tried this, but it looks like I'm messing up the logic of the ternary somehow:
type Info = { info: string; hasInfo: boolean };
type Color = { color: string; hasColor: boolean };
type Data = { data: string };
function foo<T>(
props: keyof T extends keyof Info ? Data & Info : Data & Color
) {
console.log("bar");
}
foo({ data: "hello", color: "hello", hasColor: true }); <----TypeScript gives Error
The first way works but looks so ugly.
Argument of type '{ data: string; color: string; hasColor: boolean; }' is not assignable to parameter of type 'Data & Info'. Object literal may only specify known properties, and 'color' does not exist in type 'Data & Info'.ts(2345)foocall. The error is slightly different, but I still don't see what you are expecting.data, color, hasColorordata, info, hasInfo. Not any other combination. I'm trying to achieve dev.to/maissenayed/conditional-react-props-with-typescript-43lg but with generics.