cefn / watchable

Repo for @watchable/store and supporting packages.
MIT License
5 stars 1 forks source link

feat: remove Immutable utility type from core interfaces #42

Closed cefn closed 9 months ago

cefn commented 9 months ago

This substantial change in signature eliminates a core dependency on Immutable, with the aim that Immutable is elective by the creators of a store. It's still strongly recommended, (but not enforced).

This is important if the immutable operations you are using on your store state come from a world without compile-time immutability. Even though they in practice never make changes, APIs often declare e.g. doTheThing<Arr extends number[]>(entries:Arr) not doTheThing<Arr extends readonly number[]>(entries:Arr) which would be required for it to accept an Immutable<number[]>.

However, operating WITHOUT Immutable should be done with care, and because you prefer THAT hassle (incautious mutation of state which shouldn't be mutated) versus the hassle of readonly markers throughout your data.

So instead of their being magic to transform your State into an Immutable<State>, with all reads and selected values being wrapped in Immutable<> with a signature like this...

export type CounterState = {
  counter: number;
};

export const store = createStore<CounterState>({
  counter: 0,
})

You opt-in explicitly, which has no effect on any calls YOU make, but radically simplifies the type gymnastics for special cases since Immutable is in the original type you specify, rather than needing selective transforms as read/write boundaries are crossed.

export type CounterState = Immutable<{
  counter: number;
}>;

export const store = createStore<CounterState>({
  counter: 0,
})

Potentially there could be a utility type to simplify opting into immutability to embody the recommendation, like...

export const store = createImmutableStore({some:"value"})