【问题标题】:React Redux Typescript - how to set types?React Redux Typescript - 如何设置类型?
【发布时间】:2021-10-27 07:31:13
【问题描述】:

我很难设置这个函数的类型:

interface fetchedCountries {
    mergedArray?: [];
}

export const fetchCountries = () => {
    return (dispatch:(() => void)) => {
        console.log(dispatch)
        fetch(countryListJsonFile)
            .then((response) => response.json())
            .then((jsonData: fetchedCountries) => {
                const array = Object.entries(jsonData)[0];
                const countries = array[1].map((el: any) => {
                    return el._id;
                }).sort();
                dispatch(setCountries(countries));
            })
            .catch(function (err) {
                console.error(err);
            });
    };
};

上面写着setCountries expected 0 arguments, but got 1

我尝试遵循不同的指南,例如 this,但我无法成功。 我迷路了。我想在这里摆脱所有any类型,并提供真实的。

商店已导出:

export type RootState = ReturnType<typeof store.getState>;
export type AppState = ReturnType<typeof rootReducer>;
export type AppDispatch = typeof store.dispatch;

这是切片:

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
    countryList: [],
};

const slice = createSlice({
    name: 'countryList',
    initialState,
    reducers: {
        setCountries(state, action) {
            state.countryList = action.payload;
        },
    },
});

export const { setCountries } = slice.actions;
export default slice.reducer;

有人可以帮忙吗?

【问题讨论】:

  • 你是如何定义 setCountries 的?
  • setCountries 在代码中没有说明。
  • 正如上面 cmets 所述,我怀疑您没有正确定义 setCountries() 动作创建者,我相信它必须是 const setCountries = (country: string) =&gt; ({type: YOUR_CORRESPONDING_ACTION_TYPE_HERE, country}) 之类的东西
  • 我刚刚添加了切片。请检查我原来的问题

标签: reactjs typescript redux redux-toolkit


【解决方案1】:

其实问题出在返回函数的参数类型上。

你返回了(dispatch: ((/* no parameters */) =&gt; void)) =&gt; {},但你调用了dispatch(setCountries(countries)),它有一个参数setCountries(countries)。设置正确数量的参数将修复,例如return (dispatch: ((something: unknown) =&gt; void)) =&gt; {}

【讨论】:

  • return (dispatch: AppDispatch) =&gt; {
  • 感谢您的澄清;我没怎么用过 Redux,所以不知道它的正确类型。
【解决方案2】:

您的代码中有一些问题都是相关的。您需要正确定义:

  1. dispatch 的类型在您的 fetchCountries 函数中。
  2. payload 对应于setCountries 的类型。
  3. 您所在州的类型。
  4. API 响应的类型。

链中较高的类型不正确或缺失可能会导致问题进一步下降。例如,当您发现自己在 .map() 回调中设置类型时,如下所示:

array[1].map((el: any) => {

这意味着数组本身 (array[1]) 的类型错误。所以让我们找出问题所在。


1。调度类型

@T.D.石心是对的。 expected 0 arguments, but got 1 错误来自于调用dispatch(...),而不是来自于调用setCountries(...)

您的定义dispatch:(() =&gt; void)dispatch 不接受任何参数。这显然是不正确的。

好消息是您的代码中其他地方已经有了正确的类型。它是您从商店文件中导出的AppDispatch

export const fetchCountries = () => {
    return (dispatch: AppDispatch) => {

此修复足以解决所有带红色下划线的错误。但您可能还需要修复一些其他错误和遗漏。


2。负载类型

如果您没有明确设置setCountries(state, action) 的类型,那么您的有效负载类型将变为any。这很好,但并不理想。它说“任何事情都会发生”,这会让人很难看到真正的问题。

要为操作分配正确的类型,请为 redux 工具包导入 PayloadAction 实用程序类型:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

并将其与您的有效载荷类型(国家数组)一起使用。看看你的 thunk,这些似乎是 string?:

reducers: {
    setCountries(state, action: PayloadAction<string[]>) {
        state.countryList = action.payload;      
    },
},

3。状态类型

还记得我说过any可以隐藏真正的问题吗?如果您按照第 2 步操作,那么您现在应该会看到其中之一。

state.countryList = action.payload; 的赋值报错:

类型 'string[]' 不能分配给类型 'never[]'。

您的state.countryList 具有never[] 类型,因为它的初始值为[],这就是TypeScript 所知道的一切。它不知道这应该是一个国家 ID 数组。您可以通过为您的 `initialState 分配更准确的类型来解决此问题。

要么这样做:

const initialState = {
    countryList: [] as string[],
};

或者这个:

interface SliceState { // can name it whatever
    countryList: string[];
}

const initialState: SliceState = {
    countryList: [],
};

这里有一个正确的类型将使使用您从您的状态中选择的数据变得更加容易,因为现在RootState 具有countryList 属性的正确类型。


4。 API 响应类型

interface fetchedCountries {
    mergedArray?: [];
}

这种类型表示来自您响应的 JSON 是一个对象,它可能具有属性 mergedArray这是一个空数组。就是这样。

我不确定实际数据是什么样的,但可能是这样的?

interface Country {
    _id: string;
}

interface FetchedCountries {
    mergedArray: Country[];
}

所以现在你不需要使用 (el: any),因为 TypeScript 已经知道 el 是一个 Country 对象。

.then((jsonData: FetchedCountries) => {
    const countries = jsonData.mergedArray
        .map(el => el._id)
        .sort();
    dispatch(setCountries(countries));
})

TypeScript Playground Link

【讨论】: