Object.entries/values incorrectly narrows
Closed this issue ยท 3 comments
๐ Search Terms
Object.entries Object.values
๐ Version & Regression Information
This has existed since Typescript 3.9.7, which is when definitions for Object.entries/values were added.
โฏ Playground Link
๐ป Code
const MyObj = {
expectedkey: "hi"
} as const
type MyObjType = typeof MyObj
function OnlyMyObj(obj: MyObjType){
// val is improperly(??) narrowed down to "hi"
for (const [key, val] of Object.entries(obj)){
console.log(key, val)
}
for (const val of Object.values(obj)){
console.log(val)
}
}
function test() {
const more = {
expectedkey: "hi",
unexpectedkey: "boo"
} as const
OnlyMyObj(MyObj)
OnlyMyObj(more)
}
test()๐ Actual behavior
The type for val in OnlyMyObj() is incorrectly narrowed to "hi" when it's entirely possible to get other values if there are unexpected keys.
๐ Expected behavior
Since the key from Object.entries/keys is currently not narrowed to account for cases of there being extraneous keys, I believe the proper type for val would be unknown.
Additional information about the issue
Typescript already catches a very similar error and has the error at the call site which would be preferable to changing the return type of entries/values. Not sure if that can be done though.
const MyObj = {
expectedkey: "hi"
} as const
type MyObjType = typeof MyObj
function OnlyMyObj(obj: Record<string,"hi">){
// val is improperly(??) narrowed down to "hi"
for (const [key, val] of Object.entries(obj)){
console.log(key, val)
}
for (const val of Object.values(obj)){
console.log(val)
}
}
function test() {
const more = {
expectedkey: "hi",
unexpectedkey: 9
} as const
OnlyMyObj(MyObj)
OnlyMyObj(more)
}
test()This may be a dupe of #38520, I think this is a little more specific though. I don't think Object.entries and Object.values have to be return unknown in all cases, just in this case where it narrows to literal. Maybe it would narrow to the primitive and treat the Readonly<Object> like a Record?
Duplicate of #38520.
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.