Home > database >  Get a type to rely on another type; type conditions
Get a type to rely on another type; type conditions

Time:12-09

I have a Test component that must accept a one prop where the object must have an a field but only have an id field if the two prop is not provided. If the two prop is provided then the one prop's object must not have an id field.

How can this be achieved? The closest I could get is using this interface:

interface Test {
  one: {
    a: string;
    id?: number;
  };
  two?: number;
}

Obviously it will not work properly since the id field and two props are just set to optional rather than conditioning from each other.

Here is the demo I have built:

export default function App() {
  return (
    <div>
      <Test
        one={{
          a: 'valid example with id and no two prop',
          id: 5,
        }}
      />

      <Test
        one={{
          a: 'valid example with two prop and no id field',
        }}
        two={9}
      />

      <Test
        one={{
          a: 'should have id or two prop; needs to error',
        }}
      />

      <Test
        one={{
          a: 'cannot have both id field AND two prop; needs to error',
          id: 2,
        }}
        two={5}
      />
    </div>
  );
}

interface Test {
  one: {
    a: string;
    id?: number;
  };
  two?: number;
}

const Test = ({ one, two }: Test): JSX.Element => {
  return <p>test</p>;
};

Stackblitz demo: https://stackblitz.com/edit/react-ts-2wsnwj?file=App.tsx

I wondered whether I could write the types like this, but apparently not:

type One = {
  a: string
  id?: number
}

type Two = One.id ? number : null

Any advice would be appreciated, thank you

CodePudding user response:

make Test a union type which covers all acceptable states:

type Test = {one: {a: string; id: number}} | 
            {one: {a:string}; two:number}
  • Related