LazioTibijczyk
LazioTibijczyk

Reputation: 1937

Generic Enum parameter

I created a function which takes a specific type of enum value to determine a colour to pass as a prop to another function. I would like to be able to throw a different enum at my function. I have thought of generic type but TypeScript complains:

AccountState' is not comparable to type 'T'.

enum AccountState {
  Active = 'Active',
  Deactivated = 'Deactivated'
}

const Indicator = (props: { state: AccountState }) => {
  let indicatorColor: string;

  switch (props.state) {
    case AccountState.Active:
      indicatorColor = 'green';
      break;
    case AccountState.Deactivated:
      indicatorColor = 'red';
      break;
  }

  return (
    <span
      style={{
        width: '10px',
        height: '10px',
        borderRadius: '50%',
        backgroundColor: indicatorColor,
      }}
    />
  );
};

This way I am able to render <Indicator state={Status.Active} /> however, I would also like to support this enum.

enum PaymentState {
  Paid = 'Paid',
  Unpaid = 'Unpaid',
  Pending = 'Pending'
}

I have tried the following

const Indicator = <T,>(props: { state: T }) => {
  let indicatorColor: string;

  switch (props.state) {
    case AccountState.Active: // AccountState' is not comparable to type 'T'.
    case PaymentState.Paid:
      indicatorColor = 'green';
      break;
    case AccountState.Deactivated:
    case PaymentState.Unpaid:
      indicatorColor = 'red';
      break;
  }

  return (
    <span
      style={{
        width: '10px',
        height: '10px',
        borderRadius: '50%',
        backgroundColor: indicatorColor,
      }}
    />
  );
};

Upvotes: 1

Views: 712

Answers (1)

You need to put appropriate constraint for T:

import React from 'react'

enum AccountState {
    Active = 'Active',
    Deactivated = 'Deactivated'
}

enum PaymentState {
    Paid = 'Paid',
    Unpaid = 'Unpaid',
    Pending = 'Pending'
}

type Union = AccountState | PaymentState

type Props = {
    state: Union
}

const Indicator = (props: Props) => {
    let indicatorColor: string;

    switch (props.state) {
        case AccountState.Active: {
            indicatorColor = 'green';
            break;
        }

        case AccountState.Deactivated: {
            indicatorColor = 'red';
            break;
        }

        case PaymentState.Paid: {
            indicatorColor = 'azure';
            break;
        }

        default: {
            indicatorColor = 'default value'
        }
    }

    return (
        <span
            style={{
                width: '10px',
                height: '10px',
                borderRadius: '50%',
                backgroundColor: indicatorColor,
            }}
        />
    );
};

Playground

P.S. it is considered a good practice to wrap your case expressions into { ... }

Upvotes: 1

Related Questions