Description
Suggestion
Narrowing the key obtained by iterating through Object.entries()
does not narrow the type of the value associated with that key. I.e., inside for (const [key, value] of Object.entries(x)) {…}
, x[key]
can have its type narrowed by narrowing key
, but the type of value
will not be narrowed, even though the two are equivalent.
Right now, it feels somehow like a surprise that x[key]
is not the same as value
and x[key]
needs to be evaluated again, even though that was the original goal of using the iterator.
🔍 Search Terms
object type narrowing key value
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript codeThis wouldn't change the runtime behavior of existing JavaScript codeThis could be implemented without emitting different JS based on the types of the expressionsThis isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)This feature would agree with the rest of TypeScript's Design Goals.
⭐ Suggestion
📃 Motivating Example
Example (Playground):
type X = {a: number, b: number, c: string};
function isKeyToNumber(s: string): s is 'a' | 'b' {
return s === 'a' || s=== 'b';
}
export function doubleNumbers(x: X): void {
for (const [k, v] of Object.entries(x)) {
if (isKeyToNumber(k)) {
const y = v * 2; // v is not known to be a number ❌
const z = x[k] * 2; // x[k] is known to be a number ✅
}
}
}
I ran into this issue while writing a sort function for a TypeScript-first vCard parser, which I mis-attributed first.
💻 Use Cases
Enumerating through objects which have different types for their values based on the key, e.g.
- for databases
- JSON inputs
- vCards
- …
Right now,
for…of
cannot be reasonably used there, as the value's type is not narrowed, unless re-fetched from the record; and- the developer is confused why the same data has two different types, depending on how they try to get at it.
Activity
MartinJohns commentedon Nov 7, 2021
This sounds like a duplicate of #35873.
MarcelWaldvogel commentedon Nov 7, 2021
I do not think it is a duplicate, but they probably should be implemented together, even though the key/value case might be easier to implement.
MartinJohns commentedon Nov 8, 2021
I don't see how this could be implemented without a very specific implementation just for
Object.entries()
, and that would be silly and counterproductive. But I'd love to learn and be corrected.andrewbranch commentedon Nov 8, 2021
It is a duplicate of #35873—this is just a specific example where it would be nice to have #35873.
typescript-bot commentedon Nov 11, 2021
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.