<Button/>
component that has the following props: { size?: 'sm' | 'md' | 'lg' }
, and the following usage: <Button size="sm"/>
. We get the bright idea to encode these props as booleans, such that our props are now { sm?: boolean; md?: boolean; lg?: boolean }
, which lets us do <Button sm/>
, <Button md/>
, and <Button lg/>
. This is kind of neat, but what happens when someone does <Button sm md/>
? This is an invalid combination of props.<Route/>
component. Three props are provided to handle rendering: component
, render
, and children
, and only one of the three should be provided.You should use only one of these props on a given<Route>
. See their explanations below to understand the differences between them.
component
, render
and children
is provided, but not multiple. So how do we get our BetterRouteProps
?children
doesn't exist, so we only have to deal with component
and render
. Now, we need some sort of binary type combinator that requires exactly one of the two arguments. This is just the exclusive OR (XOR).XOR<T, U>
that returns a type that enforces that either T
or U
is implemented, but not neither, and not both.XOR
. I've adapted the one that I thought was clearest to the example below:XOR
is a binary type constructor. However, recall that XOR
is both commutative and associative. Thus, we can compose our XOR
s to allow for any number of interfaces to verify.XOR
s as we need.type XOR<T, K extends keyof T>
that can be used like type EvenBetterRouteProps = XOR<RouteProps, 'render' | 'component' | 'children'>
, I'd love to see it! Currently it doesn't seem possible to create a non-record mapped type, but I've been surprised before.XOR
). Thanks!