Home > Net >  Define the use of one property or another - React Typescript
Define the use of one property or another - React Typescript

Time:09-12

I have this Button component

// React
import React from 'react'

interface ButtonProps = {
  onAction?: () => void
  onDoubleAction?: () => void
}

const Button: React.FC<ButtonProps> = ({
  onAction,
  onDoubleAction
}: ButtonProps) => {
  // Event 'click' on button
  const handleClick = () => {
    // Call 'onAction' or 'onDoubleAction'
  }

  return (
    <button type="button" onClick={handleClick}>
      button example
    </button>
  )
}

export default Button

My problem is when I invoke the button, for example

<div>
  <Button onAction={onAction}  onDoubleAction={onDoubleAction} />
</div>

I would like that, if exists 'onAction' and 'onDoubleAction' props, typescript show error 'You can use only onAction or onDoubleAction but do not both' . I want that the button only can receive 'onclick' event or 'doubleclick' event, but if receive both events, typescript returns an error to make it known that only one of the two can be used

For example

<div>
  <Button onAction={onAction} /> // Good
</div>

<div>
  <Button onDoubleAction={onAction} /> // Good
</div>

<div>
  <Button onAction={onAction} onDoubleAction={onAction} /> // Error in component
</div>

Thanks!!

CodePudding user response:

You can do this with union types!

type onAction = { onAction: () => void; onDoubleAction?: never };
type onDoubleAction = { onAction?: never; onDoubleAction: () => void };
type ButtonProps = onAction | onDoubleAction;

export const UnionButton: React.FC<ButtonProps> = (t) => {
  const handleClick = () => {
    // Call 'onAction' or 'onDoubleAction'
    const key = Object.keys(t)[0] as keyof typeof t;
    const func = t[key] as () => void;
    func();
  };

  return (
    <button type="button" onClick={handleClick}>
      button example
    </button>
  );
};
const SomeButtons = () => {
  return (
    <>
      <UnionButton onAction={() => console.log("single")} />         //happy
      <UnionButton onDoubleAction={() => console.log("double")} />   //happy
      <UnionButton                                                   //sad
        onAction={() => console.log("single")}
        onDoubleAction={() => console.log("i will create type error")}
      />
    </>
  );
};
  • Related