-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infer keyof Obj
instead of string in for(key in obj)
loops and Object.keys()
#44706
Comments
keyof Obj
instead of string in for(key in obj)
loops and Object.keys()
keyof Obj
instead of string in for(key in obj)
loops and Object.keys()
It isn't, though. Have you read https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript ? |
Indeed ! Sorry about that, I guess I was too focused on my use-case (I hit this issue a few time in the past days and was getting annoyed). So it is more complicated than I thought. Nevertheless, I still think there is an ergonomics issue. I understand we have to opt-in into having I guess we can do Would it make sense to have a for(const key in obj as WithTypedKeys<Obj>) // infers key as keyof Obj From a developper point of view I think this would at the same time clearly indicate the opt-in, and not be too verbose. But I guess it's not easy to implement (distinguish |
We don't add new top-level helpers unless they're necessary for declaration emit, since people have varying opinions about what kind of constraints they should have. Ultimately the knowledge that the object you have has no aliased properties is an assumption, and type assertions are there to encode your assumptions (or external knowledge). |
Understood, thanks for your feedback |
Suggestion
π Search Terms
for in loop
string keyof infer
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Object.keys(obj as Obj)
should have static typeArray<keyof Obj>
instead ofstring[]
in
for(key in obj as Obj)
,key
should have static typekeyof Obj
instead ofstring
Even when objects have well known keys, it is a common practice in javascript to iterate dynamically over the keys using Object.keys or for..in loops.
In typescript it is a bit convoluted to achieve, which confuses newcomers and is a bit painful because:
Object.keys()
always returnsstring[]
and infor(key in object)
, key is always inferred asstring
object[key]
only work with strings if we explicitly declared a string index in the type declaration ofobject
π Motivating Example
This code is sound, in the sense that it wouldn't generate runtime errors or violate (implicit) code invariants and hypothesis. But it doesn't compiles in typescript. To make matter worse, when reading the error, one could be tempted to change the
Conf
interface to:And indeed, the code then compiles. Unfortunately, doing so just made the code less type-safe, by broadening the
Conf
interface too much for no real reason. I think this is related to this issue about the error wording.The better solution, would be to change the offending line with:
This compiles, and does what we want. But I find it a bit verbose, and generaly I'm not a fan of casts.
I tried changing the type at the for loop instead, but no luck:
This is a bit frustrating because for me this is kind of the definition of
keyof
so it's unfortunate.Maybe I missed something, an there are probably some corner-case like Record<number, any> where
keyof
would not be backward compatible withstring
. But for the most part, I think it shouldn't break anything. Corner cases could be handled using a more complex definition:keyof
is compatible withstring
, then usekeyof
string
π» Use Cases
There are many use-cases. Javascript (and by extension typescript) is very dynamic, and there are many situations when it makes sense to iterate on objects keys instead of duplicating code: generic checks, deep copies, deep transformations, mixins, and many more.
I feel like there is a broader issue at play, where this kind of small grains of sand add up, and kind of push away developers away from some coding patterns in favor of object oriented paradigm. But hopefully I'm mistaken, and this is probably not the place for this discussion.
The text was updated successfully, but these errors were encountered: