试图编写一个可以接受可选参数并基于该参数的函数's类型,筛选并返回一个图标



我有两个单独的警报图标函数,它们是用我在React应用程序中使用的TypeScript编写的。

一个功能在学校的标题级别运行,并显示整个组织的警报。另一个功能在各个学校级别运行,只显示该位置的警报。

这两个函数几乎完全相同,本着DRY的精神,我试图编写一个可以在应用程序的任何地方使用的函数,无论是在顶层还是在位置级别。

我遇到的问题是,每个警报函数的数据元素都是不同的类型,在标头级别,该函数接收一个具有顶级属性"alertType"的对象,而位置级别的函数接收具有嵌套属性"summary"的对象,我不知道如何编写函数来接受任何一种类型作为参数,然后根据传入的内容生成适当的图标。

我试图编写几个单独的if语句来检查参数上是否存在某个属性,并在此基础上执行函数的其余部分,但TypeScript不断抛出错误,称为property does not exist on type: LocationAlerts | Summary[] | null

我有我最初的顶级警报和学校位置警报功能,并举例说明了它们的调用方式,以及我目前为这两个功能创建单一功能的尝试。

School top level function

export const showWeatherAlertIcon = (summary: Summary[] | null) => {
if (!summary) {
return false;
}
const filteredAlerts = summary.filter(a => a.alertType.toUpperCase() === 'WEATHER');
return filteredAlerts.length > 0 ? true : false;
};
export const showSpecialEventIcon = (summary: Summary[] | null) => {
if (!summary) {
return false;
}
const filteredAlerts = summary.filter(a => a.alertType.toUpperCase() === 'SPECIALEVENT');
return filteredAlerts.length > 0 ? true : false;
};
// Example of how the function is called
export const AlertSummary = () => {
const store = SchoolStore.useStore();
const alerts = store.get('schoolAlertsTop');
return (
<>
{alerts && alerts.data && (
<IconSection>
{showWeatherAlertIcon(alerts.data.alertSummary) && (
<TooltipHover toolTipContent={'INCLEMENT WEATHER'}>
<span>
<WeatherIcon />
</span>
</TooltipHover>
)}
...
</IconSection>
)}
</>
);
};

Examples of School Location Level function

export const showWeatherAlertIcon = (locationAlerts: LocationAlerts | null) => {
if (!locationAlerts || !locationAlerts.alertSummary) {
return false;
}
const filteredAlerts = locationAlerts.alertSummary.filter(a => a.alertType.toUpperCase() === 'WEATHER');
return filteredAlerts.length > 0 ? true : false;
};
export const showSpecialEventIcon = (locationAlerts: LocationAlerts | null) => {
if (!locationAlerts || !locationAlerts.alertSummary) {
return false;
}
const filteredAlerts = locationAlerts.alertSummary.filter(
a => a.alertType.toUpperCase() === 'SPECIALEVENT'
);
return filteredAlerts.length > 0 ? true : false;
};
// Example of how the function is called
<AlertContainer>
{!location.alertDetails ||
!location.alertDetails.alertSummary ||
location.alertDetails.alertSummary.length === 0 ? (
<NoAlerts>NO ALERTS</NoAlerts>
) : (
<IconBox title={`ALERTS`}>
<div className="alert-icon-container">
{showWeatherAlertIcon(location.alertDetails) && (
<TooltipHover toolTipContent={'INCLEMENT WEATHER'}>
<span>
<WeatherIcon />
</span>
</TooltipHover>
)}
...
</IconBox>
)
</AlertContainer>

Example of Single Function for both

export const showWeatherAlertIcon = (alerts: Summary[] | LocationAlerts | null) => {
if (!alerts) {
return false;
}

if (alerts && alerts.alertSummary) {
const filteredAlerts = alerts.alertSummary.filter(a => a.alertType.toUpperCase() === 'WEATHER');
return filteredAlerts.length > 0 ? true : false;
}
if(alerts){
const filteredHeaderAlerts = alerts.filter(a => a.alertType.toUpperCase() === 'WEATHER');
return filteredHeaderAlerts.length > 0 ? true : false;
}
};

它失败了,因为我认为LocationAlerts类型中的alertSummary不可以为null?如果你让它可以为null,那么我认为你的代码可能会工作。

一个更好的方法是创建一个类型保护来确定哪种类型的"警报",例如

const isLocationAlerts 
= (alerts: Summary[] | LocationAlerts): alerts is LocationAlerts 
=> (alerts as LocationAlerts).alertSummary !== undefined

然后像这样使用:

export const showWeatherAlertIcon = (alerts: Summary[] | LocationAlerts | null) => {
if (!alerts) {
return false;
}
// Note: Not sure of your alert type so I've set it to any
const isWeatherAlert = (alert: any) => alert.alertType.toUpperCase() === 'WEATHER';
return isLocationAlerts(alerts) ?
alerts.alertSummary.some(isWeatherAlert) : 
alerts.some(isWeatherAlert);
};

最新更新