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