2
const obj = {
    a: 1,
    b: 'foo',
};

for (const k of (Object.keys(obj) as (keyof typeof obj)[])) {
    obj[k] = obj[k];
}

TS Playground: https://www.typescriptlang.org/play?#code/MYewdgzgLgBCBGArGBeGBvAUDHMCGAXDAIwA02u8RA5AGYgjXkC+A3JpvQE4wAUokWAGs4tPgHkkAU2BQAdEKkBPCLwSIAlPgh9FSkGKhKADlINwkGgNoBdDVqy4LiK0Jupnrm+2ZA

I'm getting:

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

obj has different value types for each key and I want to maintain the value type for each key. In other words, I want obj.a to remain number and obj.b to remain string. I'm assuming this error is occurring because TS expects the type of obj[k] to be string | number.

Is there a way to make TS maintain the correct value type for each key?

2
  • 1
    While not a strict duplicate (as far as I know) see this and this for explanation and solutions. Remember too that in order to pull out a type from a collection the type must be statically knowable, and obj could have properties of multiple types at runtime. Commented Jun 16, 2021 at 3:00
  • why don't use Object.assign. Like this: Object.assign(obj, {a:20}); Or Object.assign(obj, {a:20, b:"another foo"}); Commented Jun 16, 2021 at 8:09

1 Answer 1

1

Here is one way, using generics to get the key as a type K instead of as a runtime value k:

const obj = {
    a: 1,
    b: 'foo',
};

function set<K extends keyof typeof obj>(k : K) {
    obj[k] = obj[k];
}

for (const k of (Object.keys(obj) as (keyof typeof obj)[])) {
    set(k);
}

Playground link

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

Comments

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.