I'd like to know if it's possible to extend a type depending on another type's value?
interface NavType {
hideNav?: boolean
dev?: boolean
}
I'd like to allow the use of hideNav
only if the dev
arg is false.
const Navbar: React.FC<NavType> = ({ children, hideNav, dev = false }) => (
<nav>
{!dev ? (
<NavDefault hideNav={!!hideNav}>{children}</NavDefault>
) : (
<NavDev>{children}</NavDev>
)}
</nav>
)
How can I use conditionals in this case?
// Should PASS
const navArgs1: NavType = {
hideNav: undefined,
dev: true
}
const navArgs2: NavType = {
hideNav: true or false,
dev: false
}
// Should NOT PASS
const navArgs3: NavType = {
hideNav: true or false,
dev: true
}
CodePudding user response:
You can define 2 types and let the component properties be their union; in principle the following (shown as TS Playground code):
interface NavBase {
dev: boolean;
}
interface DevNavType extends NavBase {
dev: true;
hideNav?: undefined;
}
interface NotDevNavType extends NavBase {
dev: false;
hideNav: boolean;
}
// This simulates your component
function f(x: DevNavType | NotDevNavType) {
}
f({ dev: true }); // Works
f({ dev: true, hideNav: undefined }); // Also works
f({ dev: false, hideNav: true }); // Works too - for any boolean value of hideNav
f({ dev: false }); // Compiler error
f({ dev: true, hideNav: true }); // Compiler error
Notes:
- You don't really need the base interface,
NavBase
- You may want to define a type for the union, to keep the code clear:
type NavType = DevNavType | NotDevNavType