我的路由器有一个useReducer
,而initialState却有一个错误Argument of type 'StateInterface' is not assignable to parameter of type 'never'.
,这仅在我在globalState.tsx的reducer中使用action.value
时才开始发生。
(Router.tsx)
import React, { useReducer } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { Layout } from './components/layout';
import { Dispatch, Global, InitialState, Reducer } from './globalState';
import { Home } from './routes/home';
import { NotFound } from './routes/notFound';
const Router: React.FC = () => {
const [global, dispatch] = useReducer(Reducer, InitialState); //<==== Here is the error
return (
<Dispatch.Provider value={{ dispatch }}>
<Global.Provider value={{ global }}>
<BrowserRouter>
<Route
render={({ location }) => (
<Layout location={location}>
<Switch location={location}>
<Route exact path='/' component={Home} />
<Route component={NotFound} />
</Switch>
</Layout>
)}
/>
</BrowserRouter>
</Global.Provider>
</Dispatch.Provider>
);
};
export { Router };
然后全局状态类似于
(globalState.tsx)
import { createContext } from 'react';
interface StateInterface {
warningMessage: string;
warningShow: boolean;
}
interface ActionInterface {
type: string;
value: string | boolean;
}
const Dispatch = createContext({
dispatch: (action: ActionInterface) => {
//
},
});
const InitialState: StateInterface = {
warningMessage: '',
warningShow: false,
};
const Global = createContext({
global: InitialState,
});
const WARNING_TOGGLE = 'WARNING_TOGGLE';
const WARNING_MESSAGE = 'WARNING_MESSAGE';
const Reducer = (state: StateInterface, action: ActionInterface) => { // <= if I change ActionInterface to any the probem goes away, but my linter then fires of with no any allowed
switch (action.type) {
case 'WARNING_TOGGLE':
return {
...state,
warningShow: action.value, // <== If I remove `action.value and set this to `true` the error goes away
};
case 'WARNING_MESSAGE':
return {
...state,
warningMessage: action.value, // <== If I remove `action.value and set this to `some string` the error goes away
};
default:
return state;
}
};
export { Reducer, InitialState, Dispatch, Global, WARNING_TOGGLE, WARNING_MESSAGE };
和首页
(home.tsx)
import React, { useContext } from 'react';
import { Dispatch, Global, WARNING_MESSAGE, WARNING_TOGGLE} from '../globalState';
const Home: React.FC = () => {
const { global } = useContext(Global);
const { dispatch } = useContext(Dispatch);
const openWarning = () => {
dispatch({ type: WARNING_TOGGLE, value: true});
};
const closeWarning = () => {
dispatch({ type: WARNING_TOGGLE, value: false});
};
const warningMessageVerify = () => {
dispatch({ type: WARNING_MESSAGE, value: 'Please verify your email'});
};
const warningMessageOffine = () => {
dispatch({ type: WARNING_MESSAGE, value: 'You are now offline'});
};
return (
<section>
{global.warningShow && <div>Warning Open</div>}
{!global.warningShow && <div>Warning Closed</div>}
{global.warningMessage}
<br/>
<button onClick={openWarning}>Open Warning</button>
<button onClick={closeWarning}>Close Warning</button>
<button onClick={warningMessageVerify}>Verify Email</button>
<button onClick={warningMessageOffine}>Offline</button>
</section>
);
};
export { Home };
答案 0 :(得分:3)
Typescript无法确定从IActionInterface
value: string | boolean
到StateInterface
warningShow: boolean
的安全类型转换,此代码为warningShow: action.value
。它不能安全地假设value
仅包含布尔值。
有几种方法可以抑制这种情况,一个简单的方法是-
warningShow: action.value as boolean
warningMessage: action.value as string
as
关键字将断言value
的类型是boolean
或string
。
答案 1 :(得分:1)
最佳做法是分别为动作创建者定义类型。
代替
{m:for pc | self.eAllContents(pa::PhysicalComponent)}
{m:pc.MatrixFlow()}
{m:endfor}
使用两个接口并基于该接口定义类型
interface ActionInterface {
type: string;
value: string | boolean;
}
在Reducer中
interface IActionInterface {
type: string;
}
interface IMessageActionInterface extends IActionInterface {
value: string;
}
interface IShowActionInterface extends IActionInterface {
value: boolean;
}
type ActionTypes = IMessageActionInterface | IShowActionInterface;
答案 2 :(得分:0)
这似乎很奇怪,如果您没有从箭头函数中显式返回某些内容。我认为这被解释为“从不”。因此,对我来说,这似乎是个问题。如果我错了,对此表示抱歉。
const Dispatch = createContext({
dispatch: (action: ActionInterface) => {
//
},
});
答案 3 :(得分:0)
该问题与您构造ActionInterface
类型并将其用于化简器的方式有关。
您需要的是让TypeScript在将其传递给switch语句时区分操作结构。
解决此问题的最佳方法是简单地给TypeScript一个有关您的操作和所拥有的联合类型的提示。
中的示例