0

I am trying to iterate array in object using variable as the object property name but it just not works.. Is there a way to do it?

This is my code:

interface Task {
    id: number;
    title: string;
}

interface AgendaState {
    todayTasks: Task[];
    nextTasks: Task[];
}

const state: AgendaState = {
    todayTasks: [
        { id: 1, title: 'Task Title' },
        { id: 2, title: 'Task Title 2' },
    ],
    nextTasks: [
        { id: 3, title: 'Task Title 3' },
        { id: 4, title: 'Task Title 4' },
    ]
};

const theFrames = {
    TODAY: 'todayTasks',
    NEXT: 'nextTasks'
};

const typeFrame = theFrames.TODAY;


const task: Task = { id: 1, title: 'Replace Task Title' }
const replacedTaskList = state[typeFrame].map(t => t.id === task.id ? task : t);
// OR
// const filteredTaskList = state[typeFrame].filter(t => t.id !== task.id);
1
  • What do you mean by "it just not works"? This is not a way to frame a question on StackOverflow Commented Jan 7, 2023 at 10:22

1 Answer 1

2

The problem is typescript is calculating theFrames type as {TODAY: string; NEXT: string; }, but string can't be used as key of state.

Easiest way to fix it:

interface Task {
  id: number;
  title: string;
}

interface AgendaState {
  todayTasks: Task[];
  nextTasks: Task[];
}

const state: AgendaState = {
  todayTasks: [
    { id: 1, title: 'Task Title' },
    { id: 2, title: 'Task Title 2' },
  ],
  nextTasks: [
    { id: 3, title: 'Task Title 3' },
    { id: 4, title: 'Task Title 4' },
  ]
}

const theFrames = {
  TODAY ='todayTasks',
  NEXT = 'nextTasks',
} as const

const task: Task = {id: 1, title: 'Replace Task Title'};

const replacedTaskList = state[Frames.TODAY].map(t => t.id === task.id ? task : t);
const filteredTaskList = state[Frames.TODAY].filter(t => t.id !== task.id);

Another way:

interface Task {
  id: number;
  title: string;
}

enum Frames {
  TODAY = 'todayTasks',
  NEXT = 'nextTasks',
}

type AgendaState = Record<Frames, Task[]>;

const state: AgendaState = {
  [Frames.TODAY]: [
    { id: 1, title: 'Task Title' },
    { id: 2, title: 'Task Title 2' },
  ],
  [Frames.NEXT]: [
    { id: 3, title: 'Task Title 3' },
    { id: 4, title: 'Task Title 4' },
  ]
}

const task: Task = {id: 1, title: 'Replace Task Title'};

const replacedTaskList = state[Frames.TODAY].map(t => t.id === task.id ? task : t);
const filteredTaskList = state[Frames.TODAY].filter(t => t.id !== task.id);
Sign up to request clarification or add additional context in comments.

5 Comments

It's still not type safe though
If you want to add something, write more...? @geoffrey
What would happen if you added a value in your enum that is not in state?
Yep! Referencing Frames directly in state's properties creates an unnecessary indirection for the reader so I would rollback that change but it's definitely an improvement
The problem of directly accessing state['wrongProp'] still remains, but it is more of a design problem than a typing issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.