0

I've seen other StackOverflow answers, but none of them seem to be working. Here is the error I am getting:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Paycheck'.
  No index signature with a parameter of type 'string' was found on type 'Paycheck'.

I get this when I try to iterate over the Array<Paycheck>, and use their keys to get their value. Is there anything wrong with the way I have created my types?

const seperated: Record<string, Array<string>> = {
    date: [],
    taxes: [],
    benefits: [],
    retirement: [],
    takeHome: [],
    total: [],
  };

type Paycheck = {
  date: string;
  taxes: number;
  benefits: number;
  retirement: number;
  takeHome: number;
  total: number;
};

// removing some code to go straight to forEach loop
// p is of type Paycheck
paychecks.forEach(p => {
    // seperated is pretty much the keys of paycheck
    Object.keys(seperated).forEach(key => {
      // p[key] is throwing the error I mentioned before
      seperated[key].push(p[key]);
    });
  });

What am I doing wrong? How do I add an index signature appropriately? I've looked at other solutions and can't get it to work.

2
  • 1
    seperated is pretty much the keys of paycheck. Can you provide the variable declaration for seperated ? Commented Feb 6, 2022 at 3:19
  • @YongShun I added it to my post! Commented Feb 6, 2022 at 7:19

1 Answer 1

1

What you can do is to get the key from Paycheck via keyof.

let k = key as keyof Paycheck;

And since all the properties (value) in seperated is with Array<string> type.

const seperated: Record<string, Array<string>> = {
  date: [],
  taxes: [],
  benefits: [],
  retirement: [],
  takeHome: [],
  total: [],
};

Hence, you need to cast the value from each property in Paycheck as string before the use of push.

seperated[k].push(p[k].toString());

Complete code

paychecks.forEach(p => { 
  Object.keys(seperated).forEach(key => {
    let k = key as keyof Paycheck;
    seperated[key].push(p[k].toString());
  });
});

Sample Demo on Typescript Playground


Unless you define the indexable key signature for the Type, then you can pass the key as string for index accessing for the Type:

type Paycheck = {
  date: string;
  taxes: number;
  benefits: number;
  retirement: number;
  takeHome: number;
  total: number;
  [key: string]: string | number; // Here to specify key as string and union Value type
};
seperated[key].push(p[key].toString());

Sample Demo (Define Indexable key Signature) on Typescript Playground

Sign up to request clarification or add additional context in comments.

5 Comments

That worked! I don't completely understand why I need to do things this way though. Shouldn't it be assumed that a key in an object is always a string? Or is that not a correct assumption?
No, because you didn't define the index signature for the type. I had updated my answer with the solution defining the index signature for type.
So adding [key: string]: string | number; to the type Paycheck tells Typescript that my key is a string, and my value for each key is either a string or a number?
Yes, as your clarification.
You're the best! Thank you :)

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.