1

The following code generates an type error, that I'm unable to understand. Any ideas what I'm doing wrong?

Type '(state: State) => State' is not assignable to type 'Action'.
  Types of parameters 'state' and 'state' are incompatible.
    Type 'S' is not assignable to type 'State'.

The error is generated on line 14 (const action: Action = ...).

interface IState {
  count: number;
}

class State implements IState {
  count: number;
}

type Action = <S>(state: S) => S
type Dispatch = <A extends Action>(action: A) => void

const dispatch = (action: Action) => { }

const action: Action = (state: State) => state

dispatch(action)

I expect for State and the generic type S to be compatible.

TS playground

1 Answer 1

2

Action represents a generic function. A generic function implies it can be called with any type that satisfies the type constrained for a given type parameter.

So this code compiles without any issues:

declare const action: Action;
action({ count: 0 }); //should return  {count :number } 
action({ sum: 0 });//should return  {sum :number } 
action({ msg: "Some text" });//should return  {msg:number } 

The problem is that your function (at least according to it's signature) does not satisfy this requirement. It takes in a state and returns a state. As highlighted above the requirements of action make it more flexible.

If your function is truly just an identity function you can just use any to make the function compatible with the signature

const action: Action = (state: any) => state

Or you can make the function implementation generic:

const action: Action = <T>(state: T) => state

If what you want is not a generic function (ie a function that works for any T) but a regular function with a signature that can be customized for a given type, you need to put the type argument on Action:

type Action<S> = (state: S) => S
type Dispatch = <A extends Action<any>>(action: A) => void

const dispatch = (action: Action<any>) => { }

const action: Action<IState> = (state) => state
    //declare const action: Action;
action({ count: 0 });
action({ sum: 0 }); // error
action({ msg: "Some text" }); // error


dispatch(action)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.