[Advanced] Props: Pass One ONLY IF the Other Is Passed - memoized arrow function
RemyMachado opened this issue · comments
What cheatsheet is this about? (if applicable)
Props: Pass One ONLY IF the Other Is Passed
Advanced cheatsheet
What's your issue or idea?
I'm struggling to make it work with an arrow function component using React.memo
.
here's the component declaration:
type CommonProps = { foo: string }
type Props1 = CommonProps & { bool: true }
type Props2 = CommonProps & { bool: false, additionalProp: number }
const MyComponent: React.FC<Props1 | Props2> = React.memo(({ foo, bool, additionalProp /* error here */ }) => {
...
})
I'm getting the following error for Props2
that defines additional props:
TS2339: Property 'additionalProp' does not exist on type 'PropsWithChildren >'.
You can define the type for the additionalProp
as never
in the case of bool === true
.
So the resulting Props1 would look like this: type Props1 = CommonProps & { bool: true, additionalProp: never }
The result is that if bool is true then the additionalProp
cannot be set otherwise you get a TypeScript error.
Within MyComponent
you'll have to check whether bool is true or false and then additionalProp
should have the correct type.
I'm not sure how I'm supposed to use the variant. If I'm omitting the additionalProp
in your playground:
test({
foo: 'foo',
bool: true
})
I'm getting:
Property 'additionalProp' is missing in type '{ foo: string; bool: true; }' but required in type '{ bool: true; additionalProp: never; }'.
Sorry, what should work is type Props1 = CommonProps & { bool: true, additionalProp?: never }
(adding the question mark to the definition of additionalProp
)
But I just saw that this yields a weird error message when trying to pass additionalProp
along with a bool
value of true.
Another solution might be using unions of two conditional types but you'll have quite some generics in there (in short in the function test
we expect an object that has a bool
property of type boolean. Then we forward this to our ResultingProps
type and TypeScript checks with the conditionals which type is it by checking if our bool
is true
or false
): https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gWwXAdgBQE5zAZygXigG8oAzOOALih2AwEsUBzKAXwChRIpNscBGArETJ0WXFABkxKACMKAG2p0ArhAA0UAIYATHfWD1UWhbzAB+aiggA3CBjadw0MzgBMQ+ElSupM+XBKZCY4Gtp6BkYoJmZWKgiy9o7sAPQpXNAAShA4KgqGzL6EroIAPjzi7gDcTtzZufmMTK4APAAqAHxCABRtUBAAHsAQKDp4RAFBqtCsUOYVfIJWtvYAlFDlvf1DI2PEk9SkITNzC7gey3YYqzXspCooAMaGqFDDtO3bw6PjB3KKEC0KFYHW6RHIcE0k00un0L2ipnErGo9TyBWalXaHXWRHYUHxUHopCg3UmBHwhGmOLxBNpj1QtHCcKiJiEsMixkR2CqUDSUAAFlo8BkoA8dBBSIwIDoafjZhAFKFiLLaVB6ShGez4azCFqWVywDy+YLhc4oCh4okMCqOBxODlgC1XG5QbjaRDqAByCGe9Qqv5HRUaFV6zmxKD8disVbse0fEqulUeqDeii+-2KZQYNRRmOxvkAIQoCAAhHHHQmwUmKF6fX7aX9pvWCaGEeHI9H2EA
To check how to use generics in combination with JSX, please refer to https://mariusschulz.com/blog/passing-generics-to-jsx-elements-in-typescript
Yet another solution (and probably the easiest and least fancy) would be to not try to destructure the props in the function signature but instead receive it as the object props
and check with a type-guard if it's the one or the other type. I haven't tested it but this simpler solution might be the best :-)
Making the additionalProp
an optional never
is working on my side. Which error did you encounter?
Another solution might be using unions of two conditional types but you'll have quite some generics
Yes, it's not ideal.
receive it as the object props and check with a type-guard
Yes, it would work, but I really wanted to learn a way to do it with destructuration.
Thank you for these solutions!
thanks Remy!