将 Slice.js 文件转换为 ts(redux 工具包)时出现类型错误

I got Type-errors while converting my Slice.js file to ts (redux tool kit)

我刚刚使用 js 文件创建了示例 Redux 工具包。现在我正在尝试将它们转换为打字稿。一些错误现已修复。但我不知道如何解决下面的两个错误。

  1. 属性 'name' 在类型 'void' 上不存在。 <<<< 也用于电子邮件、密码...和令牌
  2. 计算的 属性 名称必须是 'string'、'number'、'symbol' 或 'any' <<<< 类型 signupUser.fulfilled, signupUser.pending...等等

请参考我在下面代码中的评论,请帮助我解决问题

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from "axios";


export interface UserState {
  username: string;
  email: string;
  isFetching: boolean;
  isSuccess: boolean;
  isError: boolean;
  errorMessage: string;
}

interface check {
  name: string;
  email: string;
  password: string;
}

const initialState: UserState = {
  username: "",
  email: "",
  isFetching: false,
  isSuccess: false,
  isError: false,
  errorMessage: "",
}



export const signupUser = createAsyncThunk(
  'users/signupUser',
// 
// 
// async ({ name, email, password} ... <<<  This is the problem 1. 
//

  async ({ name, email, password }, thunkAPI) => {
    try {
      const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            name,
            email,
            password,
          }),
        },
      );
      const data = await response.json();
      console.log('data', data);

      if (response.status === 200) {
        localStorage.setItem('token', data.token);
        return { ...data, username: name, email };
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      return thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const loginUser = createAsyncThunk(
  'users/login',
  async ({ email, password }, thunkAPI) => {
    try {
      const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/auth',
        {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            email,
            password,
          }),
        },
      );
      const data = await response.json();
      console.log('response', data);
      if (response.status === 200) {
        localStorage.setItem('token', data.token);
        return data;
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const fetchUserBytoken = createAsyncThunk(
  'users/fetchUserByToken',
  async ({ token }, thunkAPI) => {
    try {
     const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          method: 'GET',
          headers: {
            Accept: 'application/json',
            Authorization: token,
            'Content-Type': 'application/json',
          },
        },
      ); 
      /* test case for Axios
      const response = await axios.get(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          headers: {
            Accept: 'application/json',
            Authorization: token,
            'Content-Type': 'application/json',
          },
        },
      );
        */
      const data = await response.json();
      console.log('data', data, response.status);

      if (response.status === 200) {
        return { ...data };
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      return thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const userSlice = createSlice({
  name: 'user',
  initialState: {
    username: '',
    email: '',
    isFetching: false,
    isSuccess: false,
    isError: false,
    errorMessage: '',
  },
  reducers: {
    clearState: state => {
      state.isError = false;
      state.isSuccess = false;
      state.isFetching = false;

      return state;
    },
  },
////
//// [signupUser.fulfilled] ... <<<< this is the problem 2.
////
////
  extraReducers: {
    [signupUser.fulfilled]: (state, { payload }) => {
      console.log('payload', payload);
      state.isFetching = false;
      state.isSuccess = true;
      state.email = payload.user.email;
      state.username = payload.user.name;
    },
    [signupUser.pending]: state => {
      state.isFetching = true;
    },
    [signupUser.rejected]: (state, { payload }) => {
      state.isFetching = false;
      state.isError = true;
      state.errorMessage = payload.message;
    },
    [loginUser.fulfilled]: (state, { payload }) => {
      state.email = payload.email;
      state.username = payload.name;
      state.isFetching = false;
      state.isSuccess = true;
      return state;
    },
    [loginUser.rejected]: (state, { payload }) => {
      console.log('payload', payload);
      state.isFetching = false;
      state.isError = true;
      state.errorMessage = payload.message;
    },
    [loginUser.pending]: state => {
      state.isFetching = true;
    },
    [fetchUserBytoken.pending]: state => {
      state.isFetching = true;
    },
    [fetchUserBytoken.fulfilled]: (state, { payload }) => {
      state.isFetching = false;
      state.isSuccess = true;

      state.email = payload.email;
      state.username = payload.name;
    },
    [fetchUserBytoken.rejected]: state => {
      console.log('fetchUserBytoken');
      state.isFetching = false;
      state.isError = true;
    },
  },
});

export const { clearState } = userSlice.actions;

export const userSelector = (state: { user: UserState}) => state.user;

您需要为放入其中的参数定义类型。如果您只想键入第一个参数并且可以使用 thunkAPI 的默认值,则可以使用

export const signupUser = createAsyncThunk(
  'users/signupUser',
  async ({ name, email, password }: ArgumentType, thunkAPI) => {

否则,您必须按照 https://redux-toolkit.js.org/usage/usage-with-typescript#createasyncthunk

中所述声明通用参数
const fetchUserById = createAsyncThunk<
  // Return type of the payload creator
  MyData,
  // First argument to the payload creator
  number,
  {
    dispatch: AppDispatch
    state: State
    extra: {
      jwt: string
    }
  }
>('users/fetchById', async (userId, thunkApi) => {

对于问题 #2,我们不鼓励 extraReducers 的对象映射表示法,因为它通常类型安全性较低,并且在 TypeScript 中不起作用。请使用 https://redux-toolkit.js.org/api/createSlice#the-extrareducers-builder-callback-notation

中描述的构建器符号