reactjs - 即使参数的类型正确,Typescript 编译错误
问题描述
打字稿抛出这个编译错误:
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
我的功能如下所示:
function todos(state: string, action: Action<string>)
我无法理解的是,首先,state
参数不可为空,但编译器却说它可以为空。其次,错误消息自相矛盾,在第一行中说函数的类型是(state: string, action: Action<string>) => string
(这是正确的),而第三行说第一个参数是string | undefined
!
我刚刚开始学习 typescript 和 react-redux,所以我真的很困惑。
编辑:
此外,我尝试调用作为第一个参数传递的函数,undefined
但编译器抱怨它不像预期的那样可以为空,但后来又抱怨它可以为空!
编辑 2
我忘了说我正在使用该函数从 reduxtodos
调用函数,如下所示:createStore
createStore(todos)
完整的代码是这样的:
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();
另外,我知道combineReducers
通常使用它并且不state
应该是 a string
,但我纯粹出于好奇(作为打字稿的初学者)问这个问题,因为我知道有明显的解决方法。
我也尝试使用string[]
作为状态的类型,但抛出了相同的错误,除了它是string[] | undefined
在这个时候。
编辑 3:
我意识到如果我为状态添加一个默认值,例如function todos(state: string = "", action: Action)
,错误就会消失。但这是为什么呢?鉴于 state 已经是必需的、不可为空的参数,这不是多余的吗?在 Swift 和 Kotlin 中,只有当您使用 nil 状态参数调用函数时才会抛出错误todos
,但您不需要在参数的定义中提供默认值。那么为什么打字稿会出现这种情况呢?这是设计使然吗?
解决方案
回答编辑 3 中提到的确切问题,使函数参数成为默认值(正如您通过为 指定默认值所做的那样state
)将此类参数的类型更改为string | undefined
(在您的情况下)。这也相当于参数后的问号。所以下面三个函数的调用签名是一样的
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>)
我从 Typescript 文档中推荐这一章。
本主题开头的错误指出,Type 'string | undefined' is not assignable to type 'string'.
因此添加默认值使其成为满足编译器state
的类型。string | undefined