“状态”类型的参数不能分配给“从不”类型的参数

时间:2019-10-29 11:29:19

标签: javascript reactjs typescript react-hooks

我刚开始在React中使用Typescript。我尝试将其与React useReducer挂钩一起使用,但是由于一个奇怪的错误而卡住了。

这是我的代码:

Field f = obj.getClass().getDeclaredField("AssName"); //NoSuchFieldException
f.setAccessible(true);
String assignmentName = (String) f.get(obj); 

当我将鼠标悬停在 export interface ContractObj { company: string; negotiationRenewalDate: string; periodEnd: string; periodStart: string; scheduleForRenewal: boolean; contractId: string; } type State = { loading: boolean; error: boolean; contractsData: ContractObj[]; }; type Action = | { type: 'FETCH_SUCCESS'; payload: ContractObj[] } | { type: 'FETCH_ERROR'; payload: null }; const initialState: State = { loading: true, error: false, contractsData: [] }; const reducer = (state: State, action: Action) => { switch (action.type) { case 'FETCH_SUCCESS': return { loading: false, error: false, contractsData: action.payload }; case 'FETCH_ERROR': return { loading: false, error: true }; default: { return state; } } }; export const Contracts: React.FC<Props> = () => { const [state, dispatch] = useReducer(reducer, initialState); 上时,这给我一个错误,即类型'S​​tate'的参数不能分配给'never'类型的参数

1 个答案:

答案 0 :(得分:1)

确保始终在State函数中返回相同的reducer类型。如果将鼠标悬停在reducer上,则会看到它当前具有以下签名:

const reducer: (state: State, action: Action) => State | {loading: boolean; error: boolean;}

那是因为在case 'FETCH_ERROR'中遗漏了contractsDataStatereducer中被定义为必填属性。通过向const reducer = (state: State, action: Action): State => { ... } 函数添加显式返回类型,可以轻松解决该问题:

contractsData

,您会得到(在这种情况下令人满意!)编译错误,抱怨缺少属性。最后,您可以在'FETCH_ERROR'的情况下添加一个空的State数组,或者在switch (action.type) { case 'FETCH_ERROR': return { loading: false, error: true, contractsData: [] } } 类型中将该属性定义为可选。

解决方案1:

type State = {
    loading: boolean;
    error: boolean;
    contractsData?: ContractObj[];
};

解决方案2:


class _MyHomePageState extends State<MyHomePage> {
  Ads appAds;
  final String appId = Platform.isAndroid
      ? 'ca-app-pub-9010870803829618~619xxxxxxx'
      : 'ca-app-pub-9010870803829618~390xxxxxxx';

  final String bannerUnitId = Platform.isAndroid
      ? 'ca-app-pub-9010870803829618/936xxxxxx'
      : 'ca-app-pub-9010870803829618/83xxxxxxx';
...

  var eventListener = (MobileAdEvent event) {
      if (event == MobileAdEvent.opened) {
        print("The opened ad is clicked on.");
      }
    };

appAds = Ads(
      appId,
      bannerUnitId: bannerUnitId,
      screenUnitId: screenUnitId,
      listener: eventListener,
);
...

    appAds.setBannerAd(
      adUnitId: bannerUnitId,
      size: AdSize.fullBanner,
      anchorType: AnchorType.bottom,
      anchorOffset: 50.0,
    );

Playground