I've been learning Typescript by creating a Task Manager app with React and Redux. I am trying to send my state to Redux as an array of dictionaries but the problem is that I need to declare an empty array of dictionaries before I can send my state through it.
Here is my App.tsx
file:
import React, { FC, useState } from "react"
import { useSelector, useDispatch } from "react-redux"
import TodoList from "./Components/TodoList"
import NameTodo from "./Components/NameTodo"
import { RootState } from "./todoStore"
import { createTodoCard } from "./todoReducer"
interface TodoListTemplate {
title: string,
id: number,
}
const App: FC = () => {
// Contains all the generated todo-lists
const [generatedTodoList, setGeneratedTodoList] = useState<any[]>([]);
const selector = useSelector((state: RootState) => { return state.todo });
const dispatch = useDispatch();
const generateTodoList = (): void => {
// Sending this to the Redux state as an array of dictionaries
const todoList: TodoListTemplate = {
title: selector.todoCardName,
id: Math.floor(Math.random() * 10000),
}
setGeneratedTodoList([...generatedTodoList, todoList]);
// Reducer that would send todoList to the Redux state
dispatch(createTodoCard(generatedTodoList));
}
return (
...
)
}
export default App
And here is my todoReducer.ts
file:
import { createAction, createReducer, PayloadAction } from '@reduxjs/toolkit'
export const update = createAction<any[]>('update')
export const toggleNaming = createAction<boolean>('toggleNaming')
export const addTodoName = createAction<string>('addTodoName')
//This is the reducer that would send the todoList to the array of dictionaries
export const createTodoCard = createAction<Record<string, number>[]>('createTodoCard')
export const todoReducer = createReducer(
{
todoList: [''],
toggleNamingMenuState: false,
todoCardName: '',
// It should be sent here
todoCard: [],
},
(builder) => {
builder
.addCase(update, (state, action: PayloadAction<any[]>) => {
state.todoList = action.payload
})
.addCase(toggleNaming, (state, action: PayloadAction<boolean>) => {
state.toggleNamingMenuState = action.payload
})
.addCase(addTodoName, (state, action: PayloadAction<string>) => {
state.todoCardName = action.payload
})
.addCase(createTodoCard, (state, action: PayloadAction<Record<string, number>[]>) => {
state.todoCard = action.payload
})
}
)
export default todoReducer
I have tried using Record<k, v>
but I am not sure if I'm using it correctly.
Here is the error that is being shown:
Type 'Record<string, number>[]' is not assignable to type 'never[]'.
Type 'Record<string, number>' is not assignable to type 'never'.
Thank you for the responses in advance :)
CodePudding user response:
When you declare the array, you need to specify the type it is.
{
todoList: [''],
toggleNamingMenuState: false,
todoCardName: '',
// It should be sent here
todoCard: [] as Array<Record<string, number>>,
}
Either do it this way as a hackish way, or go full throttle and create an interface for it, or specify the type of the whole object for the reducer initializer. example:
{
todoList: [''],
toggleNamingMenuState: false,
todoCardName: '',
// It should be sent here
todoCard: [],
} : {
todoCard: Array<Record<string, number>>,
...
}