#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>
);
};
Комментарии:
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. Другим вариантом было бы убедиться, что рассматриваемые переменные правильно заданы как пустые строки.