Я сделал простой <If />
компонент функции, используя React:
import React, { ReactElement } from "react";
interface Props {
condition: boolean;
comment?: any;
}
export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
if (props.condition) {
return <>{props.children}</>;
}
return null;
}
Это позволяет мне писать более чистый код, такой как:
render() {
...
<If condition={truthy}>
presnet if truthy
</If>
...
В большинстве случаев это работает хорошо, но когда я хочу, например, проверить, не задана ли данная переменная, а затем передать ее как свойство, это становится проблемой. Я приведу пример:
Допустим, у меня есть компонент с именем, <Animal />
который имеет следующие реквизиты:
interface AnimalProps {
animal: Animal;
}
и теперь у меня есть другой компонент, который отображает следующий DOM:
const animal: Animal | undefined = ...;
return (
<If condition={animal !== undefined} comment="if animal is defined, then present it">
<Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
</If>
);
Как я уже говорил, хотя на самом деле animal не определена, у меня нет возможности сообщить Typescript, что я его уже проверил. Утверждение animal!
будет работать, но это не то, что я ищу.
Любые идеи?
javascript
reactjs
typescript
Элия Коэн
источник
источник
{animal !== undefined && <Anibal animal={animal} />}
, сработает<Animal animal={animal as Animal} />
Ответы:
Это кажется невозможным.
Причина: если мы изменим содержимое
If
компонента снапротив
Вы обнаружите, что на этот раз вы хотите, чтобы тип diff обрабатывался противоположным образом.
Это означает, что он не является независимым, что приводит к выводу, что невозможно создать такой тип в этом состоянии, не касаясь ни одного из двух компонентов.
Я не уверен, что лучший подход, но вот одна из моих мыслей.
Вы можете определить
Animal component
реквизитыanimal
с помощью машинописиусловных типов Distributive текста : NonNullable .
Документ
Применение
Он не генерируется
If
условием компонента, но поскольку вы используете толькоchild component
внутри этого условия, имеет смысл разработатьchild component
реквизиты какnone nullable
, при условии, чтоисточник
Короткий ответ?
Ты не можешь
Поскольку вы определили
animal
какAnimal | undefined
, единственный способ удалитьundefined
это либо создать охрану, либо преобразоватьanimal
как-то еще. Вы скрыли охрану типов в свойстве условия, и TypeScript не знает, что там происходит, поэтому он не может знать, выбираете ли вы междуAnimal
иundefined
. Вам нужно будет разыграть его или использовать!
.Однако подумайте: это может показаться чище, но оно создает фрагмент кода, который должен быть понят и поддержан, возможно, кем-то еще в дальнейшем. По сути, вы создаете новый язык, состоящий из компонентов React, который кто-то должен будет выучить в дополнение к TypeScript.
Альтернативный метод условного вывода JSX состоит в определении переменных, в
render
которых содержится ваш условный контент, напримерЭто стандартный подход, который другие разработчики сразу узнают и не должны искать.
источник
Используя обратный вызов рендеринга, я могу напечатать, что возвращаемый параметр не имеет значения NULL.
Я не могу изменить ваш оригинальный
If
компонент, так как я не знаю, какой у васcondition
утверждаете, а также какую переменную он утверждал, т.е.condition={animal !== undefined || true}
К сожалению, я создал новый компонент
IsDefined
для этого случая:Указывает, что
children
это будет обратный вызов, которому будет передан NonNullable типа T, того же типа, что иcheck
.При этом мы получим обратный вызов рендеринга, которому будет передана переменная, проверенная нулем.
У меня есть рабочий пример здесь https://codesandbox.io/s/blazing-pine-2t4sm
источник
If
компонента (чтобы он мог выглядеть чисто)