0

How to correctly write this in Typescript?

var obj = {
  kv: {
    foo: 'bar',
    bar: 'baz'
  }
};

for(const k in obj.kv) {
  const v = obj.kv[k];
  obj.kv[k] = 'prefix' + v; 
  // error TS7017: Index signature of object type implicitly has an 'any' type.
}

// desired output:
// { kv: { foo: 'prefixbar', bar: 'prefixbaz' } }

I want to update each item on the obj.kv object.

3 Answers 3

2

You can refactor it this way:

var obj = {
  kv: {
    foo: 'bar',
    bar: 'baz'
  }
};

for (const k of Object.keys(obj.kv))
{
  const v = (obj.kv as any)[k];
  (obj.kv as any)[k] = 'prefix' + v;
}
Sign up to request clarification or add additional context in comments.

1 Comment

sorry I was looking at the other answer, upvoted! (still think mine is better :p)
2
const obj = {
  kv: {
    foo: 'bar',
    bar: 'baz'
  }
};

Object.entries(obj.kv).forEach(([key, value]) => {
  obj.kv[key] = `prefix${value}`; 
});

Note that the entries method was added in ECMAScript 2016. If you do not have it available, natively or via a polyfill, you can write

Object.entries(obj.kv)
  .map(key => [key, obj.kv[key]])
  .forEach(([key, value]) => {
    obj.kv[key] = `prefix${value}`; 
  });

instead.

3 Comments

this is more beautiful, but TS2339 entries does not exists in ObjectConstructor
It is a fairly recent language addition. It may not be in your browser. Sorry about that
@Kokizzu I revised my answer with an explanation as well as an example that does not rely on Object.entries but preserves the fluent characteristics and destructuring. Thanks again for your comment.
1

While a bit verbose, this would be more type-friendly:

var obj = {
  kv: {
    foo: 'bar',
    bar: 'baz'
  } as {
      [key:string]: string,
  }
};

for (const k of Object.keys(obj.kv)) {
  const v = obj.kv[k];

  // error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
  // const erroneous = Math.round(v);  

  obj.kv[k] = 'prefix' + v; 
}

1 Comment

instead of as { [key:string]: string }, you could write for (const k of Object.keys(obj.kv).map(k => k as keyof typeof obj.kv)) { const v = obj.kv[k]; }. That way, you don't lose strong typing on subsequent property accesses to obj.kv

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.