Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use HOC with redux compose and Typescript

I have two HOC, which want to use with redux compose, but the compiler doesn't make correct type. Compose declares function is from redux source code. If we paste the code in the playground. We will see different types of first and second variables.

type Func1<T1, R> = (a1: T1) => R

type Component<Props> = (props: Props) => string;

declare function compose<T1, A, R>(
  f1: (b: A) => R,
  f2: Func1<T1, A>
): Func1<T1, R>

declare const HOC1: <Props>(component: Component<Props>)
    => Component<Props & { prop: string }>

declare const HOC2: <Props>(component: Component<Props>)
    => Component<Props & { prop: number }>

declare const component: Component<{props: boolean}>

const first = HOC1(HOC2(component));

const second = compose(HOC1, HOC2)(component);
like image 984
Dominion Avatar asked Jan 24 '19 20:01

Dominion


People also ask

Can you use TypeScript with Redux?

TypeScript is a typed superset of JavaScript that provides compile-time checking of source code. When used with Redux, TypeScript can help provide: Type safety for reducers, state and action creators, and UI components. Easy refactoring of typed code.

How do I use compose in Redux?

Compose is used when you want to pass multiple store enhancers to the store. Store enhancers are higher order functions that add some extra functionality to the store. The only store enhancer which is supplied with Redux by default is applyMiddleware however many other are available.


1 Answers

We can't model a good version of compose in the current typescript type system. There is no way to capture generic type parameters to the HOCs.

We can create a version that might work in some circumstances based on the way the type parameters get erased (basically they are just replaced with the narrowest type in this case {}). This means we can get the props that are added by the HOC. I don't know how well this will work, but it does work for your sample:

type Func1<T1, R> = (a1: T1) => R

type Component<Props> = (props: Props) => string;

declare function compose<A, R, R2>(f1: (b: A) => Component<R>,f2: (b: A) => Component<R2>,): (<P>(c: Component<P>) => Component<P & R & R2>)

declare const HOC1: <Props>(component: Component<Props>)
    => Component<Props & { prop1: string }>

declare const HOC2: <Props>(component: Component<Props>)
    => Component<Props & { prop2: number }>

declare const component: Component<{props3: boolean}>

const a = HOC1(HOC2(component));

const b = compose(HOC1, HOC2)(component); //Component<{ props3: boolean; } & { prop1: string; } & { prop2: number; }>

Playground link

like image 99
Titian Cernicova-Dragomir Avatar answered Sep 27 '22 20:09

Titian Cernicova-Dragomir