I want to add functions to an Enum type in my React Functional Components (i.e. classless) TypeScript project.
As already asked and answered here, this can be done in one of two ways:
class ModeUtil {
public static toString(mode: Mode) {
return Mode[mode];
}
or
enum Mode {
X,
Y
}
namespace Mode {
export function toString(mode: Mode): string {
return Mode[mode];
}
export function parse(mode: string): Mode {
return Mode[mode];
}
}
Since I have been able to avoid classes in my project so far, I prefer keeping it that way and thus I'm in favor of the namespace approach.
However, the namespace approach is in violation with the no-namespace ESLint rule.
Hence, is use of classes a valid approach after all? I mean, in React, functional components were introduced in favor of classes to avoid mutation. In this context, the class itself would only contain static methods...
CodePudding user response:
I don't think the React choice to move away from classes is something that means "In general, classes are bad and should be avoided". It just means "In React, a component can be better expressed and easily defined with a function component".
So answering to your question: classes ARE a valid approach in general. But it is up to you to understand if it fits your scenario. In your specific case, I think it can work smoothly. Or, if you think otherwise, you could just disable that eslint rule.
But, again, the fact that React dismissed class based components, doesn't mean that classes are bad. Just use React functional components and feel free to use classes whenever you think they could help.
CodePudding user response:
So I ended up with a third classless approach that wraps the enum functions inside an object.
Given that you have a Drink enum like this:
export enum Drink {
GinTonic,
LongIslandIceTea
}
You can then define your utils/helper functions like this:
import { Drink } from "../models/drink";
const toHumanString = (drink: Drink): string => {
switch (drink) {
case Drink.GinTonic:
return "Gin Tonic";
case Drink.LongIslandIceTea:
return "Long Island Ice Tea";
default:
throw new Error(`Unknown drink ${drink}.`);
}
};
const toMachineString = (drink: Drink) => {
switch (drink) {
case Drink.GinTonic:
return "GinTonic";
case Drink.LongIslandIceTea:
return "LongIslandIceTea";
default:
throw new Error(`Unknown drink ${drink}.`);
}
};
const parse = (drinkAsString: string): Drink => {
switch (drinkAsString) {
case "GinTonic":
return Drink.GinTonic;
case "LongIslandIceTea":
return Drink.LongIslandIceTea;
default:
throw new Error(`Failed to parse drink ${drinkAsString}.`);
}
};
export const DrinkUtils = {
parse: parse,
toHumanString: toHumanString,
toMachineString: toMachineString
};
I added a demo here.