Reputation: 65
As I know, for any type T, the keyof T
will be public property names of T, and then I see keyof any
which make me confused. Can I just simplify keyof any
to any
?
Upvotes: 5
Views: 332
Reputation: 329533
The type keyof any
isn't any
. It is string | number | symbol
:
type PropKey = keyof any
// type PropKey = string | number | symbol
The keyof
type operator results in a union of all key types which are known to be allowable for the type. So keyof any
is asking for all possible key types, since the any
type allows you to index into it with any valid key whatsoever. Not all types are valid keys, though, so keyof any
is just string | number | symbol
instead of something like the unknown
type:
declare const x: any;
x.str; // okay
x[123]; // okay
x[Symbol("")] // okay
x[new Date()] // error
x[false] // error
An equivalent type to keyof any
is provided in the TypeScript standard declaration files as PropertyKey
:
declare type PropertyKey = string | number | symbol;
Generally speaking you would probably use PropertyKey
instead of keyof any
, if you're only interested in supporting recent TypeScript versions.
The reason why you might see keyof any
is that before TypeScript 2.9, the keyof
operator would only return types assignable to string
. Starting with TypeScript 2.9, keyof
supports number
and symbol
key types as well. And PropertyKey
itself was also introduced in TypeScript 2.9.
That means if you have any TypeScript code which needs to support versions both before and after TypeScript 2.9, you can use neither PropertyKey
nor string | number | symbol
to properly constrain key types. But you can use keyof any
; in TypeScript 2.8 and below, keyof any
returns just string
, while afterward it returns string | number | symbol
. So you can write something like
type DateHolder<K extends keyof any> = { [P in K]: Date };
and it will work in both cases. It's been a while since TypeScript 2.8, though, and many breaking changes have occurred since then, so using keyof any
is probably not necessary.
Upvotes: 5