Reputation: 28654
I was using following approach for passing props conditionally (when one prop depends on another prop) in react:
type CommonProps = { age: number };
type ConditionalProps =
| {
type: 'view' | 'add';
}
| {
type: 'edit';
initialData: number;
};
let Test = (props: CommonProps & ConditionalProps) => {
return <div />;
};
My goal was:
type
is passed as "view" or "add", then I want TS to error if I pass initialData
type
is passed as "edit" then initialData
should be required.This actually worked most of the time, until value of type
was dynamic.
When I passed value of type
like this:
<Test
age={9}
type={Math.random() > 0.5 ? 'edit' : 'view'}
initialData={9}
/>
Now it seems there is bug above, because TS isn't complaining anymore, and it can happen that type
is "view" and I also pass initialData
, which violates my first goal above.
What is the solution in such case? I suppose TS should report an error? If yes, how?
Upvotes: 4
Views: 1125
Reputation: 3179
In general, Typescript ignores excess properties unless they're explicitly assigned or passed as an argument.
So, although in your example here you're passing { age: number, type: "view", initialData: number }
, that satisfies the type { type: "view" | "add" }
. This is similar to the way that, for instance, you might ignore irrelevant fields in data from an external source.
If however you really want to ban the extra prop in this instance, you can do so by specifying that its type should be never
:
type ConditionalProps =
| {
type: 'view' | 'add';
initialData?: never;
}
| {
type: 'edit';
initialData: number;
};
Note that we specify initialData
as never
and also optional, so that it may (must) be omitted.
With the never
type in place, Typescript will report an error unless the type
prop is "edit"
.
Upvotes: 2