Search code examples
reactjstypescriptgenericstypescript-genericsreact-typescript

Generics in TypeScript - Type is not assignable to type (missing the following properties)


I’ve created the following interface, type and function.

interface ActionWithGeneric<T> { 
    type: 'add' | 'remove';
    data: T;
}

type StateWithGeneric<T> = Array<ActionWithGeneric<T>>

const TodoReducerGeneric : <T,> (state: StateWithGeneric<T>, action: ActionWithGeneric<T>) => StateWithGeneric<T> = (state, action) => { 
    switch (action.type) { 
        case "add": 
            return [...state, {text: action.data}]
        case "remove": 
            return state.filter(a => action.data !== a.data)
        default: 
        return state
    }
}

Next, I’m trying to use it as follows in my React component:

const TextField : React.FC<Props> = ({text}) => { 

    const [data, dispatchData] = useReducer(TodoReducerGeneric, [])

    return (
        <div>{data}</div>
    )
}

I’m getting the following error on my TodoReducerGeneric:

Type '<T>(state: StateWithGeneric<T>, action: ActionWithGeneric<T>) => (ActionWithGeneric<T> | { text: T; })[]' is not assignable to type '<T>(state: StateWithGeneric<T>, action: ActionWithGeneric<T>) => StateWithGeneric<T>'.
  Type '(ActionWithGeneric<T> | { text: T; })[]' is not assignable to type 'StateWithGeneric<T>'.
    Type 'ActionWithGeneric<T> | { text: T; }' is not assignable to type 'ActionWithGeneric<T>'.
      Type '{ text: T; }' is missing the following properties from type 'ActionWithGeneric<T>': type, data

I understand there’s a type mismatch but I’m strugging to understand where the {text : T;} is coming from in the error message or how to fix it.


Solution

  • Well, the state of your reducer is:

    ActionWithGeneric<T>[]
    

    but you're trying to add

    {text: action.data}
    

    to this array.

    {text: action.data} isn't an ActionWithGeneric<T>, but action is...

    Did you mean:

    switch (action.type) { 
        case "add": 
            return [...state, action]
        // ...
    

    ?