2

I need to set values of fields of person object which exists in employee object. But I can't do it properly without type errors

Here is my code:

interface IPerson {
   name: string;
   age: number;
}

interface IEmployee extends IPerson {
   salary: number;
}

const PersonTemplate: IPerson = {
  name: '',
  age: 0
}

const employee: IEmployee = {name: 'Name', age: 18, salary: 1000};
const person: IPerson = {...PersonTemplate};

for (const key in PersonTemplate) {
  const keyName = key as keyof IPerson;

  if (keyName in employee) person[keyName] = employee[keyName];
}

console.log(person);

The problem on line person[keyName] = employee[keyName]. Error text:

Type 'string | number' is not assignable to type 'never'.

Type 'string' is not assignable to type 'never'.

I tried to fix this by changing the line to person[keyName] = employee[keyName] typeof person[keyName] but I get new errors:

Type 'keyName' is not assignable to type 'never'.

Type 'keyName' cannot be used as an index type.

'keyName' refers to a value, but is being used as a type here. Did you mean 'typeof keyName'?

and when I hover mouse on keyName in typeof person[keyName] TS shows me that type keyName = /*unresolved*/ any

Please show how to solve this problem properly

P.S. in real there is more fields than given 3

EzioMercer
  • 1,502
  • 2
  • 7
  • 23
  • https://effectivetypescript.com/2020/05/26/iterate-objects/ – PomPom Jun 22 '22 at 10:02
  • @PomPom This is not what I need. If I just `console.log(person[keyName])` in `for in` loop then there is no problems or errors. The problem is when I try to get value from another object – EzioMercer Jun 22 '22 at 10:06
  • 1
    THis is by design. See [this](https://stackoverflow.com/questions/67857960/how-to-selectively-assign-from-one-partial-to-another-in-typescript/67860407#67860407) and [this](https://stackoverflow.com/questions/68189542/typescript-why-cant-i-assign-a-valid-field-of-an-object-with-type-a-a-b/68190097#68190097) and [here](https://catchts.com/mutations). Workaround is [here](https://tsplay.dev/mZ4Zew) – captain-yossarian from Ukraine Jun 22 '22 at 11:09
  • @captain-yossarianfromUkraine Can you please explain why accepted answer does work? Why it is not muattion if I mutate in another function? – EzioMercer Jun 22 '22 at 12:30

1 Answers1

1

If you want to answer why, I don't know excatly why TS lost track of typings in this case.

If you want to make it works :

function copyValue<T>(k: keyof T, target: T, source: T) {
  target[k] = source[k];
}

for (const key in PersonTemplate) {
  const keyName = key as keyof IPerson;

  if (keyName in employee) {
    copyValue(keyName, person, employee);
  }
}
PomPom
  • 1,468
  • 11
  • 20