Есть ли способ, чтобы требовались два реквизита, если используется один из них?

#reactjs #typescript

Вопрос:

Я пытаюсь создать два реквизита, которые передаются в компонент, необходимый для использования одного из них.

 export type ComponentProps = {
  children: ReactNode
  height?: number
  width?: number
}

const Component: React.FC<ComponentProps> = ({
  children,
  height,
  width
}) => {...
 

Итак, как я могу сделать так, чтобы при передаче опоры высоты компонент также требовал передачи опоры ширины?

Я пробовал использовать необязательный тип объекта под названием sizeProps и деструктурировать высоту и ширину в компоненте, но этот тип, похоже, не работал. Также попытался расширить, а также попытался использовать тип утилиты Partial<> , но не смог заставить его работать. Звучит ли «Дискриминирующие союзы» как правильный подход? Хотя я не мог понять, как я должен использовать его для этого случая

Ответ №1:

В целом дискриминируемые профсоюзы помогают в решении такого рода проблем.

Вам нужен дискриминатор, который представляет собой строку, различающую (различающую) членов союза.

 type Naked = {
    type: 'naked';
    children: React.ReactNode;
};

type Sized = {
    type: 'sized';
    height: number;
    width: number;
};

type ComponentProps = Naked | Sized;

export const MyComponent: React.FC<ComponentProps> = props => {
    return props.type === 'sized' ? (
        <span>
            {
                // TS control flow "knows" that we are dealing with the "Sized" type here,
                // In other words: props are narrowed to the Size type
                props.width * 2   props.height
            }
        </span>
    ) : (
        <span>{props.children}</span>
    );
};

 

Вы можете прочитать больше об этом здесь: https://thoughtbot.com/blog/the-case-for-discriminated-union-types-with-typescript

Не уверен, что это лучший способ помочь вашему делу, хотя, возможно, сделайте шаг назад и подумайте об использовании разных компонентов для разных вещей.