eslint-plugin-react-refresh icon indicating copy to clipboard operation
eslint-plugin-react-refresh copied to clipboard

Allow constant exports doesn't work with objects.

Open AaronPowell96 opened this issue 1 year ago • 6 comments

I am looking to create some way where these constants would work. If I am able to say these are immutable with as const or if the plugin would be able to infer that simply by a full capitalisation of a variable that would be nice. If I write const MY_CONSTANT = {} I am telling you 'I will not mutate this, it is a constant'.

There should be no warning below? image

AaronPowell96 avatar Jan 19 '24 17:01 AaronPowell96

The issue is that you need also the React refresh runtime to skip that. I will probably add an option to the Vite React plugins to support Remix, and this option could be later used to support this kind of use case.

For now the safest way is to have a small file along the current file to export this constants

ArnaudBarre avatar Jan 21 '24 17:01 ArnaudBarre

It seems, that this option also doesn't involve enums?

donverduyn avatar Apr 30 '24 11:04 donverduyn

Yeah TS enums are transpiled to JS objects so they are not "constants". I encourage you to use string based enums that are ignored because type only and aligned better with the current direction of TS to not add any runtime behaviour that is not defined in JS.

ArnaudBarre avatar May 09 '24 11:05 ArnaudBarre

I agree, that it would be great to have this feature to allow enums as part of the prop definition to be exported without any issue. This seems a valid case to me.

export enum Type {
  a = "a",
  b = "b",
}

interface ComponentProps {
  type: Type;
}

export function TypeComponent({ type }: ComponentProps) {
  return <div>{type}</div>;
}

So I can use

<TypeComponent type={Type.a} />

GerroDen avatar Jul 24 '24 12:07 GerroDen

Using enum is really something that goes against the current trend of TS to be just a typechecker for JS. These kind of runtime features (enum, namespaces, parameters properties) where all added a long ago.

I strongly advised using string enums:

export Type  = "a" |  "b";

interface ComponentProps {
  type: Type;
}

export function TypeComponent({ type }: ComponentProps) {
  return <div>{type}</div>;
}
<TypeComponent type="a" />

ArnaudBarre avatar Jul 24 '24 13:07 ArnaudBarre

In vanilla JS we would likely define a constant object with these string types as values just like an enum does. It's just a shorthand. So instead of enums we would like to define:

export Type = "a" | "b";
export componentType = {
  a: "a",
  b: "b".
} as const;

Which is equal to the output of string-based enums in TS.

GerroDen avatar Jul 24 '24 14:07 GerroDen

I'm doing some cleanup of the backlog, and few months later I don't think this worth adding. This would require a lot a coordinations with bundlers and still make the rule more confusing on what can be exported. Primitive constant is good because it easy and ship to implement, but everything else then come with edge cases.

ArnaudBarre avatar Nov 24 '24 19:11 ArnaudBarre

I also have a few constants that are objects or arrays (some basically enums, some not). To clarify, @ArnaudBarre - the current recommendation when using this plugin is to move those out of the component file into their own file, correct? I.e. only exports of primitive constants can be safely ignored?

githorse avatar Jan 11 '25 18:01 githorse

Yep that's correct

ArnaudBarre avatar Jan 11 '25 18:01 ArnaudBarre