1

Im trying to make it so that if on prop is true, all others will be ignored. My current react code looks like this:

<Component isTrue={true}/>
<Component foo='bar' someProp={true}/>;

But this causes problems because in my Component.tsx file because the Props interface

interface Props {
    isTrue?: boolean;
    foo?: string;
    someProp?: boolean;
}

Typescript warns me about the props maybe being undefined which i can fix by adding more lines of code but its pretty troublesome to do everytime i make a new prop.

So i want to know if its possible to have separate props or something to fix this problem, thanks in advance :)

KyleRifqi
  • 489
  • 2
  • 15

3 Answers3

1

Because you write Typescript warns me about the props maybe being undefined, I assume you basically want to pass at least one prop to your component, but still type check the others if you pass more. You can do this by creating an interface T and a type OneOfObject, which basically makes all properties optional (Partial) but requires at least one prop(default type from keyof T).

TestComponent.tsx

type OneOfObject<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]

interface T {
    isTrue: boolean; //or isTrue: true (if you want to force it to true)
    foo: string;
    someProp: boolean;
}

const TestComponent = (props: OneOfObject<T>)=>{

  return (
  <div>{props.foo}</div>
  )
}

export default TestComponent

App.tsx

import React from "react";
import TestComponent from './TestComponent';

export default function App() {


  return (
    <div className="App">
      <TestComponent foo={`It's ok`}/>
    </div>
  );
}

You can test it out here.

MWO
  • 2,627
  • 2
  • 10
  • 25
0

Maybe an alternative way is to separate the concerns of component prop types into several (private) components. For example, for

interface Props {
    isTrue?: boolean;
    foo?: string;
    someProp?: boolean;
}
  1. For the Component, can give all props directly to <Component isTrue={true/false} foo='bar' someProp={true}/>; as optional props
  2. Inside Component, check for the isTrue. if (isTrue), return a component <TrueComponent/> where you can ignore all other props inside the logic of TrueComponent
  3. Otherwise, return another component <FalseComponent/>, where you can ignore this isTrue props, but requires all other props to be required. There would be one layer of nonnull props check that cannot be avoided in Component, but I think that would be the minimal effort and would be type-safe.
Mark
  • 999
  • 1
  • 7
  • 15
0

So, you could do it like this if you didn't want two different components.

    export type IMyComponentPropsTruth = {
      isTrue: boolean;
    };
    export type IMyComponentPropsFalse = {
      foo: string;
      someProps: string;
    };
    
    export const MyComponent = (
      props: IMyComponentPropsTruth | IMyComponentPropsFalse
    ) => {
      const mytruthyProps = props as IMyComponentPropsTruth;
      const myfalseProps = props as IMyComponentPropsFalse;
      if (mytruthyProps && mytruthyProps.isTrue) {
        return <div>THE TRUTH IS OUT THERE</div>;
      } else {
        return (
          <div>
            keep looking {myfalseProps.foo} {myfalseProps.someProps}
          </div>
        );
      }
    };

import "./styles.css";
import { MyComponent } from "./MyComponent";

export default function App() {
  return (
    <>
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
      <MyComponent isTrue={true} />
      <MyComponent foo="looked" someProps="404" />
    </>
  );
}
Nikki9696
  • 6,260
  • 1
  • 28
  • 23