0

Typescript throws this compile error:

Argument of type '(state: string, action: Action<string>) => string' is not assignable to parameter of type 'Reducer<string, Action<string>>'.
  Types of parameters 'state' and 'state' are incompatible.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.  TS2345

and my function looks like this:

function todos(state: string, action: Action<string>)

What I can't understand is, first, the state parameter is not nullable yet the compiler says it's nullable. Second, the error message contradicts itself by saying in the first line that the function's type is (state: string, action: Action<string>) => string (which is correct) whereas the third line is saying that the first parameter is string | undefined!

I'm just beginning learning typescript and react-redux so I'm really confused.

EDIT:

Further, I tried calling the function passing undefined as first argument but the compiler complains that it's not nullable as expected, yet complain later that it's nullable!

EDIT 2

I forgot to say that I'm using the todos function in calling the createStore function from redux like this: createStore(todos).

The full code is this:

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {Action, createStore} from 'redux'
import {Provider} from "react-redux";

function todos(state: string, action: Action<string>) {
    return state
}

let store = createStore(todos); // PROBLEM HERE
let app = (
    <Provider store={store}>
        <App/>
    </Provider>
)

ReactDOM.render(app, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();

Also, I'm aware that combineReducers is normally used and that state shouldn't be a string, but I'm asking this question purely out of curiosity (being a beginner in typescript) because I know that there are obvious workarounds.

I also tried using string[] as the type of the state but same error is thrown except that it's string[] | undefined at this time.

EDIT 3:

I realized that if I add a default value to the state, e.g. function todos(state: string = "", action: Action), the error will be gone. But why is this? Isn't it redundant given that state is already a required, non-nullable parameter? In Swift and Kotlin, the error will be thrown only if you call the todos function with a nil state argument, but you don't need to provide a default value in the definition of the parameter. So why is this the case in typescript? Is this by design?

2
  • 1
    It doesn't look like you've shared all relevant code here... the error is in some function that takes todos as a parameter to something, but all you've shown here is the signature of todos and not the signature of the function. Ideally you should work to provide a minimal reproducible example, preferably one where you can link to an online IDE like StackBlitz. The easier you make it for others to reproduce your error and modify your code, the likelier it will be for you to get a satisfactory answer. Good luck! Commented Apr 27, 2019 at 0:22
  • Hi @jcalz, sorry I forgot to add some info. I just edited the question and added more details. Thanks. Commented Apr 27, 2019 at 1:28

1 Answer 1

1

Answering your exact question mentioned in EDIT 3 making function parameter default (as you did by specifing default value for state) changes type of such parameter to string | undefined (in your case). This also eqvivalent to question mark after parameter. So call signatures of three functions below are the same

function todos(state: string | undefined, action: Action<string>)
function todos(state?: string, action: Action<string>)  // This example is not completly correct as you should make action optional too, by addint ? to it name
function todos(state: string = "", action: Action<string>)

I suggest this chapter from Typescript doc.

Error in the start of this topic states that Type 'string | undefined' is not assignable to type 'string'. So adding default value to state makes it of type string | undefined which satisfied compiler.

Sign up to request clarification or add additional context in comments.

1 Comment

That seems right. I actually tested that (the second case only and I didn't bother checking the first since I thought they're just equivalent) but I got thrown off because the second case produced another error (i.e. TS1016). I think this inconsistency should be fixed because it's misleading.

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.