Попытка написать функцию, которая может принять необязательный параметр и в зависимости от его типа, отфильтровать и вернуть значок - PullRequest
1 голос
/ 13 апреля 2020

У меня есть две отдельные функции пиктограмм оповещений, написанные на TypeScript, которые я использую в своем приложении React.

Одна функция запускается на уровне заголовка школы и отображает оповещения для всей организации. Другая функция запускается на уровне отдельной школы, показывая только оповещения для этого местоположения.

Обе функции почти идентичны, и в духе 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;
  }
};

1 Ответ

1 голос
/ 14 апреля 2020

Это сбой, потому что я предполагаю, что alertSummary в вашем типе LocationAlerts не обнуляется? Если вы сделаете его обнуляемым, то я думаю, что код, который у вас есть, может работать.

Лучшим подходом было бы создать type guard , чтобы определить, какой тип "alert", например,

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);
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...