zustand icon indicating copy to clipboard operation
zustand copied to clipboard

Suggestion: drop uncurried support of `create`

Open devanshj opened this issue 2 years ago • 7 comments

I've lost count of how many people have missed the extra parenthesis in create()(...) (and the wrong usage ie create(...) doesn't even get caught because it's allowed). I don't see how supporting the create(...) usage adds any value, it's just creating trouble for many people (including me). I know I've suggested this before but I want to make the suggestion official hence opening an issue.

devanshj avatar Nov 15 '22 19:11 devanshj

Thanks for opening a suggestion. Let's wait others to comment. One note is as such a change is breaking, it will be only possible in v5.

That said, my personal comment would be a) create(...) is still very valid and natural syntax for JS users, and b) create()(...) simply doesn't look comfortable, so I prefer to use create(...) without middleware, and I'm not a big fan of middleware. They are mostly preference, and my mind could be changed on this.

(I understand there are many troubles, and wonder if there's any other way to mitigate it, like warning for the usage of create(...) only in TS. Otherwise, eslint-plugin-zustand would be one solution. Or, hm, we could attach api.middlwareIsUsed property and warn it.)

dai-shi avatar Nov 15 '22 23:11 dai-shi

There's also an option to support it in runtime but not include it in types (ie .d.ts won't include the uncurried overload).

devanshj avatar Nov 16 '22 05:11 devanshj

Maybe i'm misunderstanding but is this the two types of syntaxes we're discussing?

type Test = {
  name: string;
};

const curried = create<Test>()((set) => ({ name: "Yes" }));

const uncurried = create<Test>((set) => ({
  name: "string",
}));

Personally I prefer the uncurried one and find the curried one weird.. Callback initializers are pretty common in the world of JS

Gustav-Eikaas avatar Jan 06 '23 13:01 Gustav-Eikaas

Maybe i'm misunderstanding but is this the two types of syntaxes we're discussing?

Yeah, in summary:

  • In TypeScript, the curried one is required if you use middleware (not all of them, but with store mutation, but hard to know which).
  • The curried one works for all cases, both in JavaScript and TypeScript
  • In JavaScript, the uncurried one works for all cases.

dai-shi avatar Jan 06 '23 13:01 dai-shi

We use TS, and have used the uncurried version almost exclusively, and have not had any problems, I guess because we aren't using middleware that requires it. We tend to use type inference on factory function return types for different slices, with good results.

ollwenjones avatar Jan 09 '23 15:01 ollwenjones

The idea of eslint-plugin-zustand would be great. I've been wanting to make one so we can add optional rules like always-use-selector when calling useStore in a React component.

charkour avatar Jan 09 '23 16:01 charkour

There's a way to support uncurried version for TS as well with middlewares? I would like to have just one way to do both, with and without middlewares.

dbritto-dev avatar Jan 11 '23 15:01 dbritto-dev

@dbritto-dev we aren't currying, but its fine because we aren't using middle-wares. It seems like some middle-wares require it.

ollwenjones avatar Jan 13 '23 15:01 ollwenjones

@dbritto-dev we aren't currying, but its fine because we aren't using middle-wares. It seems like some middle-wares require it.

@ollwenjones actually, I would like to have just one way to do both

dbritto-dev avatar Jan 14 '23 03:01 dbritto-dev