reactjs - 使用 Typescript 反应功能组件:Typescript 不理解更改的属性类型
问题描述
我将一个可以是字符串或对象的道具传递给反应功能组件,下面是一个示例。它无需打字稿即可工作。但是,当我添加打字稿时,它似乎不明白道具(例如下面的 helpMessage)可以是字符串或对象。
我收到这个错误
TS2339: Property 'message' does not exist on type 'string | HelpMessage'. Property 'message' does not exist on type 'string'.
import React, { FC } from 'react';
interface HelpMessage {
headerText?: string;
footerText?: string;
message?: string;
}
interface FieldProps {
name: string;
helpMessage?: string | HelpMessage;
}
const ConditionalPropsComponent: FC<FieldProps> = ({ name, helpMessage }) => {
const helpMessageIsString = typeof helpMessage === 'string';
const helpText =
helpMessage && helpMessageIsString ? helpMessage : helpMessage?.message;
return (
<div>
{helpText && !helpMessageIsString && (
<div>
<p>{helpMessage?.headerText}</p>
<p>{helpMessage?.message}</p>
<p>{helpMessage?.footerText}</p>
</div>
)}
{helpText && helpMessageIsString && <p>{helpText}</p>}
</div>
);
};
export default ConditionalPropsComponent;
错误出现在下面屏幕截图中红色摆动线的位置:
我创建了一个代码沙箱,以便您可以看到问题。 https://codesandbox.io/s/github/nfabacus/React-typescript-dynamic-type-issue/tree/main/?file=/src/index.tsx:217-226
基本上,提取条件以const helpMessageIsString = typeof helpMessage === 'string';
引发类型错误,但如果我将它们中的每一个替换为typeof helpMessage === 'string'
,错误就会消失,但这是重复的..
此外,下面的作品但感觉很hacky - helpMessage 是HelpMessage 或未定义。当我传递字符串时,它既不是 HelpMessage 对象也不是未定义的,但打字稿不会抱怨..这很奇怪。
interface HelpMessage {
headerText?: string;
footerText?: string;
message?: string;
}
interface FieldProps {
name: string;
helpMessage?: HelpMessage;
}
const ConditionalPropsComponent: React.FC<FieldProps> = ({
name,
helpMessage
}) => {
const helpMessageIsString = typeof helpMessage === 'string';
const helpText = helpMessageIsString ? helpMessage : helpMessage?.message;
....
Typescript 很棒,但在这种特殊情况下,我对 Typescript 感到有点失望,如果没有一个好的解决方案......
解决方案
您在此示例中缺少的是Type Assertion和Type Inference。
Typescript 是一个编译器,它不能在运行时中断类型。
当你编写这样的代码时,Typescript 将helpMessageIsString
类型推断为boolean
而不是“如果它是一个真实的布尔值那么helpMessage
是字符串”。
// helpMessageIsString is boolean
const helpMessageIsString = typeof helpMessage === "string";
// Typescript can't interrupt if the boolean has a meaning for true
// v string | HelpMessage
const helpText = helpMessageIsString ? helpMessage : helpMessage?.message;
使其工作的最简单方法是通过条件块使用类型推断:
if (typeof helpMessage === "string") {
// In this scope, helpMessage is a STRING
} else {
// In this scope, helpMessage is of type HelpMessage
}
对于其他不可读的解决方案,只需在类型断言文档中选择一个可用的 API。
推荐阅读
- excel - 在 Excel 工作簿中创建 PDF 书签
- python - 将 Shapely Multipoint 转换为 Pandas 数据框的优雅方法
- c - 坚持要求输入(C程序)
- sql - 迄今为止解析不同类型的值
- powershell - 使用 PowerShell 远程访问 cmd
- javascript - 如何在 jira rest api 中使用节点和 express js 仅设置基本身份验证(用户名,密码)而没有令牌 api
- spring-kafka - 使用过滤策略时如何找到接收到的事件记录数?
- vimeo-api - Vimeo API,用于当用户关闭浏览器(播放器正在运行)或浏览器意外关闭时
- visual-studio-code - VSCode:从上到下顺序问题,而不是首先出现错误,然后是警告
- python - ModuleNotFoundError:没有名为“pandas”的模块尝试了从互联网上找到的所有内容