我有以下组件,它可以包含图像或文本。因此,在 JSX 中,我检查是否有图像(因为这意味着不能有文本,反之亦然),然后显示图像或文本。
如何使用 TypeScript 类型定义此行为?
I BlockCtaDoubleData
,始终可用,并且 EITHER BlockCtaDoubleImageData
OR BlockCtaDoubleTextData
。
我尝试了以下操作,但 Typescript 不断为 props.text
和 props.image
抛出错误,但对于 props.headline
却没有。
怎么会?
interface BlockCtaDoubleData
{
headline: string;
}
interface BlockCtaDoubleImageData extends BlockCtaDoubleData
{
image: string;
alt: string;
}
interface BlockCtaDoubleTextData extends BlockCtaDoubleData
{
text: string;
}
export type BlockCtaDoubleProps = BlockCtaDoubleTextData | BlockCtaDoubleImageData;
export function BlockCtaDouble(props: BlockCtaDoubleProps)
{
return (
<div>
{props.headline}
{props.image ? (
<img src={props.image} alt={props.alt}/>
) : (
{props.text}
)}
</div>
);
}
仅供参考:错误是说计数器类型中不存在相应的道具。
答案 0 :(得分:1)
为了区分 import string
if s[0] in string.digits:
...
和 BlockCtaDoubleImageData
,你需要一个类型保护。
BlockCtaDoubleTextData
类型保护是一个返回 import React from "react";
interface BlockCtaDoubleData {
headline: string;
}
interface BlockCtaDoubleImageData extends BlockCtaDoubleData {
image: string;
alt: string;
}
interface BlockCtaDoubleTextData extends BlockCtaDoubleData {
text: string;
}
export type BlockCtaDoubleProps =
| BlockCtaDoubleTextData
| BlockCtaDoubleImageData;
const isBlockCtaDoubleImageData = (
a: BlockCtaDoubleProps
): a is BlockCtaDoubleImageData => a.hasOwnProperty("image");
const isBlockCtaDoubleTextData = (
a: BlockCtaDoubleProps
): a is BlockCtaDoubleTextData => a.hasOwnProperty("text");
export function BlockCtaDouble(props: BlockCtaDoubleProps) {
return (
<div>
{props.headline}
{isBlockCtaDoubleImageData(props) ? (
<img src={props.image} alt={props.alt} />
) : (
props.text
)}
</div>
);
}
的函数。您需要以这种方式实现它:如果 x 是 Type 则返回 true,否则返回 false。具体条件由您决定。
您无法通过您的方法实现它。你将不得不使用歧视联合。
x is Type
interface BlockCtaDoubleData {
headline: string;
type: "image" | "text";
}
interface BlockCtaDoubleImageData extends BlockCtaDoubleData {
image: string;
alt: string;
type: "image";
}
interface BlockCtaDoubleTextData extends BlockCtaDoubleData {
text: string;
type: "text";
}
export type BlockCtaDoubleProps =
| BlockCtaDoubleTextData
| BlockCtaDoubleImageData;
export function BlockCtaDouble(props: BlockCtaDoubleProps) {
return (
<div>
{props.headline}
{props.type === "image" ? (
<img src={props.image} alt={props.alt} />
) : (
props.text
)}
</div>
);
}
会抛出错误:
<BlockCtaDouble headline="as" text="xd" type="image" image="xd" />
答案 1 :(得分:1)
添加到现有答案中,您可以使用更简洁的行为 using in
operator。您可以执行以下操作:
interface BlockCtaDoubleData
{
headline: string;
}
interface BlockCtaDoubleImageData extends BlockCtaDoubleData
{
image: string;
alt: string;
}
interface BlockCtaDoubleTextData extends BlockCtaDoubleData
{
text: string;
}
export type BlockCtaDoubleProps = BlockCtaDoubleTextData | BlockCtaDoubleImageData;
export function BlockCtaDouble(props: BlockCtaDoubleProps)
{
return (
<div>
{props.headline}
{("image" in props) ? (
<img src={props.image} alt={props.alt}/>
) : (
{props.text}
)}
</div>
);
}