Home > Software design >  How can I declare an empty array of dictionaries in Typescript?
How can I declare an empty array of dictionaries in Typescript?

Time:02-05

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>>,
 ...
}
  • Related