-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
keyof
on types originating from javascript object literals is (nearly) useless
#25987
Comments
keyof
on types originating from javascript object literals is uselesskeyof
on types originating from javascript object literals is (nearly) useless
To be clear, this isn't blocking |
had an offline discussion about this, we should do the right thing and mark the types of JS object literals with a flag to allow for looser property access checking and assignablity checking, instead of manifesting an index signature. |
It is blocking it in JS, yes. |
This is not really specific to JavaScript object literals. That's just a small part of the bigger problem. It's a limitation of I came up with a little helper type that extracts all known keys: type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K
} extends {[_ in keyof T]: infer U} ? U : never; This way you don't need to change any type inference. |
Using inference to rebuild the keys sans index signature. Nifty, though very difficult to look at. It can work, though I think I'd have trouble explaining it to anyone. Still - potentially needing to perform such contortions on any type from a js object literal expression seems a bit excessive - it's certainly not what came to my mind as a solution. |
@ajafff Very clever; good work. |
@ajafff Could you please help me understand the type? How exactly is it different from |
@m93a |
I just noticed a little bug in my Here's the fixed version: type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K
} extends {[_ in keyof T]: infer U} ? ({} extends U ? never : U) : never; |
@ajafff Doesn't work with typed object literals, any ideas? type KnownKeys<T> = {
[K in keyof T]: string extends K ? never : number extends K ? never : K
} extends {[_ in keyof T]: infer U} ? ({} extends U ? never : U) : never;
type SomeType = {
[_:string]: string
}
const foo : SomeType= {
a: 'one',
b: 'two',
}
type MyKeys = KnownKeys<typeof foo> // never |
After upgrading to TS 4.3.2, for some reason it resolves to export type KnownKeys<T> = keyof { [K in keyof T as string extends K ? never : K]: K } |
Compatible with the original version for TS 4: export type KnownKeys<T> = keyof {
[K in keyof T as string extends K ? never : number extends K ? never : K]: never
} |
TypeScript Version: 3.1.0-dev.201xxxxx
Search Terms:
Code
In a js file:
Expected behavior:
keyof
returns the keys the object actually has or is declared with.Actual behavior:
keyof
returnsstring | number
, thanks the the any-index signature shoved into every object literal expression's type in JS.This came up on
DefinitelyTyped
- strongly typing react'spropTypes
is virtually impossible because all of the key filtering and mapping operations (eg,Exclude
) just don't work on any JS object literals (unless all of your keys are unique symbols (nobody would do this, I don't think), since those aren't mangled by subtype reduction with the index signature).cc @mhegazy This is a blocker in rolling out the better React inferences to our JS users.
The text was updated successfully, but these errors were encountered: