I made a simple <If />
function component using React:
import React, { ReactElement } from "react";
interface Props {
condition: boolean;
comment?: any;
}
export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
if (props.condition) {
return <>{props.children}</>;
}
return null;
}
It lets me write a cleaner code, such as:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
In most cases, it works good, But when I want to check for example if a given variable is not defined and then pass it as property, it becomes an issue. I'll give an example:
Let's say I have a component called <Animal />
which has the following Props:
interface AnimalProps {
animal: Animal;
}
and now I have another component which renders the following DOM:
const animal: Animal | undefined = ...;
return (
<If condition={animal !== undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
);
As I commented, althought in fact animal is not defined, I've got no way of telling Typescript that I already checked it. Assertion of animal!
would work, but that's not what I'm looking for.
Any ideas?
if-else statements don't work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction.
Use a ternary operator to conditionally render multiple elements in React. When returning multiple sibling elements, make sure to wrap them in a React fragment. Copied! We used a ternary operator to conditionally render multiple elements.
There are a lot of React components available on-line, and if you're using TypeScript with React, it can't sometimes be a little disappointing because many of those components don't have their type definitions.
Fear not, creating a type definition file is easy, and because you have already saved some time at work using a component built by somebody else, maybe you can use that time and collaborate creating the type definition file for the component. In my case, I was working with the react-selectize component.
What is React? I’m glad you asked! React is a development library created by Facebook which allows developers to break their code up into bite-sized, reuseable chunks called components. Components are created separately and are then put together to create a dynamic and fully functioning application.
When we build a react application, we may often need to display or hide some content based on a certain condition. Conditional rendering in react works the same way as the conditions work in JavaScript. First, we will create a new file called UserGreetings.Js; within the file, let’s create a class component.
Reason: if we change If
component's content from
if (props.condition) {
...
}
to it's opposite
if (!props.condition) {
...
}
You will find out that this time you want the type diff been processed in the opposite way.
<If condition={animal === undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
Which means it's not independent, leading to the conclusion that it's not possible to make such type diff in this condition, without touching either of the two components.
I'm not sure what's the best approach, but here is one of my thought.
You could define Animal component
's props animal
with the typescript's
Distributive conditional types: NonNullable.
Document
type T34 = NonNullable<string | number | undefined>; // string | number
Usage
interface AnimalProps {
// Before
animal: Animal;
// After
animal: NonNullable<Animal>;
}
It's not generated by the If
component's condition, but since you only use the child component
inside that condition, it makes some sense to design the child component
's props as none nullable
,under the condition that
type
Animal
do containundefined
.
Short answer?
You can't.
Since you've defined animal
as Animal | undefined
, the only way to remove undefined
is to either create a guard or recast animal
as something else. You've hidden the type guard in your condition property, and TypeScript has no way of knowing what is happening there, so it cannot know you are choosing between Animal
and undefined
. You'll need to cast it or use !
.
Consider, though: this may feel cleaner, but it creates a piece of code that needs to be understood and maintained, perhaps by someone else further down the line. In essence you're creating a new language, made of React components, that someone will need to learn in addition to TypeScript.
An alternative method to conditionally output JSX is to define variables in render
that contain your conditional content, such as
render() {
const conditionalComponent = condition ? <Component/> : null;
return (
<Zoo>
{ conditionalComponent }
</Zoo>
);
}
This is a standard approach other developers will instantly recognize and not have to look up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With