Skip to content

TypeScript definition for StoreEnhancer prevents state type extension #1648

Closed
@fdecampredon

Description

@fdecampredon

With the current type definition of StoreEnhancer:

export type StoreEnhancer<S> = (next: StoreEnhancerStoreCreator<S>) => StoreEnhancerStoreCreator<S>;
export type GenericStoreEnhancer = <S>(next: StoreEnhancerStoreCreator<S>) => StoreEnhancerStoreCreator<S>;
export type StoreEnhancerStoreCreator<S> = (reducer: Reducer<S>, initialState: S) => Store<S>;

We cannot define an enhancer that change the type of the sate :

declare function reducerWithFoo<S>(reducer: Reducer<S>): Reducer<S & { foo: string }>;

function test<S>(next: StoreEnhancerStoreCreator<S>): StoreEnhancerStoreCreator<S & { foo: string }> {
  return (reducer: Reducer<S>, initialSate: S & { foo: string }) => next(reducerWithFoo(reducer), initialSate);
}

Here we try to create an enhancer that add a foo field to the sate, but typescript errors saying (in short) that S is not compatible with S & { foo: string }.
This is due to the fact that the next function passed as arguments is not generic and so cannot capture the type from arguments.

Perhaps the solution would be to add a generic version of the StoreEnhancerStoreCreator type, and to change the signature of StoreEnhancer to use that type for the next argument.

definitions :

export type StoreEnhancer<S> = (next: GenericStoreEnhancerCreator) => StoreEnhancerStoreCreator<S>;
export type GenericStoreEnhancer = <S>(next: GenericStoreEnhancerCreator) => StoreEnhancerStoreCreator<S>;
export type StoreEnhancerStoreCreator<S> = (reducer: Reducer<S>, initialState: S) => Store<S>;
export type GenericStoreEnhancerCreator = <S>(reducer: Reducer<S>, initialState: S) => Store<S>;

example:

declare function reducerWithFoo<S>(reducer: Reducer<S>): Reducer<S & { foo: string }>;

function test<S>(next: GenericStoreEnhancerCreator): StoreEnhancerStoreCreator<S & { foo: string }> {
  return (reducer: Reducer<S>, initialSate: S & { foo: string }) => next(reducerWithFoo(reducer), initialSate);
} // no error

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions