Распознавание реквизитов Typescript в функциональном компоненте react

#javascript #reactjs #typescript #typeerror

#javascript #reactjs #typescript #ошибка ввода

Вопрос:

Я создаю динамический виджет, который может быть либо пустым, либо заполненным. По умолчанию он должен быть пустым. Когда populated={true} я бы хотел totalGross totalNet , чтобы значения and были обязательными. В противном случае эти 2 реквизита не должны быть разрешены.

Для этого я пытаюсь использовать различающий тип ( WidgetBodyProps ). Однако TypeScript жалуется, потому totalNet что amp; totalGross являются необходимыми реквизитами в <WidgetBodyPopulated />

 type WidgetBodyProps =
    | { isEmpty?: false; totalNet: string; totalGross: string }
    | { isEmpty: true; totalNet?: never; totalGross?: never };

type WidgetProps = WidgetHeaderProps amp; WidgetBodyProps;

const Widget = (props: WidgetProps) => {
    const { title = "", isEmpty = true, totalNet, totalGross } = props;

    return (
        <Card>
            <Box>
                <WidgetHeader title={title} />
                <Divider my="4" />
                {isEmpty ? (
                    <WidgetBodyEmpty flex="1" />
                ) : (
                    <WidgetBodyPopulated totalNet={totalNet} totalGross={totalGross} />
                )}
            </Box>
        </Card>
    );
};
 

Как я могу исправить эту ошибку Typescript?
Ошибка TS

Комментарии:

1. Назначение значений по умолчанию для totalNet и totalGross должно исправить немедленную ошибку (т.Е. totalNet = '', totalGross = '' ). Тем не менее, я думаю, что способ WidgetBodyProps кажется немного запутанным, особенно в never использовании. Я думаю, последнее связано с тем, что вы хотите уклониться от использования средств защиты типов?

Ответ №1:

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

Однако, если вы избегаете деструктурирования, Typescript может следить за типом props . Таким образом, тестирование preperty реквизита сужает тип реквизита, который вы ожидаете.

 {props.isEmpty ? (
    <WidgetBodyEmpty flex="1" />
) : (
    <WidgetBodyPopulated
      totalNet={props.totalNet}
      totalGross={props.totalGross}
    />
)}
 

Затем вы можете даже упростить эти реквизиты до:

 type WidgetBodyProps =
    | { isEmpty?: false; totalNet: string; totalGross: string }
    | { isEmpty: true };
 

Потому что вы никогда не получаете доступ .totalNet без предварительной проверки .isEmpty .

Рабочий пример

Ответ №2:

Обычно эта ошибка возникает из-за того, что Typescript не доверяет вам, что что-то не равно null. Используйте ненулевой оператор утверждения, чтобы сообщить Typescript, что он может доверять тому, что вы знаете, что делаете, и вы не будете вводить в него значение null. Другим вариантом было бы убедиться, что рассматриваемые переменные правильно заданы как пустые строки.