Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 基于Typescript中的类型实现特定行为_Reactjs_Typescript - Fatal编程技术网

Reactjs 基于Typescript中的类型实现特定行为

Reactjs 基于Typescript中的类型实现特定行为,reactjs,typescript,Reactjs,Typescript,我正在建立一个React网站,我想在其中显示文章(我称之为“预览”) 文章可以是文本或图像/视频。我声明了两个接口(TextPreviewProps和ImgVidPreviewProps),它们共享一些公共属性(id,type),但在其他接口上也有所不同(例如,TextPreviewProps有一个text属性,而ImgVidPreviewProps有一个文件属性) 导出接口TextPreviewProps{ id:编号; 类型:“文本”; 文本:字符串; onChangeText?:(新文本:

我正在建立一个React网站,我想在其中显示文章(我称之为“预览”)

文章可以是文本或图像/视频。我声明了两个接口(TextPreviewProps和ImgVidPreviewProps),它们共享一些公共属性(
id
type
),但在其他接口上也有所不同(例如,TextPreviewProps有一个
text
属性,而ImgVidPreviewProps有一个
文件
属性)

导出接口TextPreviewProps{
id:编号;
类型:“文本”;
文本:字符串;
onChangeText?:(新文本:字符串)=>无效;
}
导出接口ImgVidPreviewProps{
id:编号;
键入:“图像”|“视频”;
档案:档案;
}
导出类型ContentPreviewProps=TextPreviewProps | ImgVidPreviewProps;
我已经声明了一个类型别名ContentPreviewProps,它可以是TextPreviewProps或ImgVidPreviewProps

我的呈现“预览”的函数将ContentPreviewProps作为输入,我希望它根据输入是文本还是图像/视频返回不同的React组件。既然我们不能在Typescript中真正动态地进行类型检查,那么最好的方法是什么

目前,我检查
type
属性是“text”还是“image”/“video”,然后根据
type
的值将ContentPreviewProps对象强制转换为TextPreviewProps或ImgVidPreviewProps

const renderPreview=(
内容:ContentPreviewProps
):JSX.Element=>{
常量{type,id}=content;
如果(类型==“文本”){
const textContent=作为TextPreviewProps的内容;
返回(
console.log(newText)}
id={id}
/>
);
}
const imgVidContent=作为imgvidcreviewprops的内容;
返回(
);
};
但是,这种方法存在冗余,因为我必须检查
类型
,然后根据检查结果强制转换对象

在Typescript中,在运行时实现这种类型特定行为的惯用方法是什么?

当您这样做时:

export type ContentPreviewProps = TextPreviewProps | ImgVidPreviewProps;
然后,从
TextPreviewProps
ImgVidPreviewProps
中的prop
type
将确定在type
ContentPreviewProps
中指向哪一个

因此,当您收到prop
type:string=“text”
时,
ContentPreviewProps
通常是:

{
    id: number;
    type: "text";
    text: string;
    onChangeText?: (newText: string) => void;
}
因此,在使用时,您不必根据
type
prop值进行强制转换!因为您在声明该类型时已经这样做了:

export type ContentPreviewProps = TextPreviewProps | ImgVidPreviewProps;
您可以将代码修改为:

从下面的Ewaren更新来看,从
内容中销毁
类型
是问题的原因

const renderPreview=(
内容:ContentPreviewProps
):JSX.Element=>{
如果(content.type==“text”){//TS不会抱怨textContent.text,因为您正在验证它。
返回(
console.log(newText)}
id={content.id}
/>
);
}
返回(
);
};

我相信TS不会对此抱怨。由于您正在有条件地检查
类型

,因此这是一个完美的示例,TypeScript已经支持该类型。这里的问题是,您已经将
内容拉入了它自己的变量中。在检查它之前,请将
键入到它自己的变量中,哪个TypeScript不会跟随它。如果直接检查属性:
If(content.type==“text”){…}
则不需要强制转换。谢谢,这非常有效!也许你可以把这个评论变成一个答案,这样我就可以验证它了?这是我对TS的期望,但是当我按照你的解释尝试编写它时,我得到了以下错误消息:
属性“text”在类型“ContentPreviewProps”上不存在。类型“ImgVidPreviewProps”上不存在属性“text”。TS2339
。看来TS实际上不明白它需要强制转换。更新:CRice的评论解释了为什么你的解决方案不能按原样工作,我不应该在检查其类型之前对
内容进行分解。是的,你可以更新你的答案删除分解,我将验证它基本上是你的解决方案@Ewaren,我会更新我的答案,但你也可以发布你自己的答案并接受它;)
const renderPreview = (
        content: ContentPreviewProps
    ): JSX.Element => {
        if (content.type === "text") { // TS won't complain about textContent.text since you are validating it here.
            return (
                <TextPreview
                    type={content.type}
                    text={content.text}
                    onChangeText={(newText: string) => console.log(newText)}
                    id={content.id}
                />
            );
        }

        return (
            <ImgVidPreview
                type={content.type}
                file={content.file}
                id={content.id}
            />
        );
    };