Reputation: 1554
Whit an object like this
const USER_EVENT = {
pageview: 'Visit',
order: 'Order'
}
if I would to get a type with union of all keys
type UserEventKey = 'pageview' | 'order'
I could do this
type UserEventKey = keyof typeof USER_EVENT
...but is it possible to get this type with union of all values?
type UserEventName = 'Visit' | 'Order'
type UserEventName = ???? is it possibile?
Upvotes: 6
Views: 3760
Reputation: 330376
You can't use your USER_EVENT
object as written. The compiler uses some heuristics to infer the types of variables that are not annotated. Generally speaking, the compiler sees string property values as being of type string
:
const OOPS_USER_EVENT = {
pageview: 'Visit',
order: 'Order'
}
/* const OOPS_USER_EVENT: {
pageview: string;
order: string;
} */
So the compiler has forgotten about the specific "Visit"
and "Order"
values, and nothing you do with typeof USER_EVENT
will bring them back.
Instead you need to define USER_EVENT
differently. The easiest way to do that is to use a const
assertion to hint that your object won't change at all, and to ask the compiler to infer the most specific type it can:
const USER_EVENT = {
pageview: 'Visit',
order: 'Order'
} as const;
/* const USER_EVENT: {
readonly pageview: "Visit";
readonly order: "Order";
} */
Now USER_EVENT
has properties of the string
literal types "Visit"
and "Order"
; the information you care about is still there.
At this point you need to take an object type like T
and get the union of property value types instead of the keys. See this question for a more canonial version of this question and its answer.
You can use indexed access types of the form T[K]
to get the property value types at keys of type K
. If you want all keys, then T[keyof T]
works:
type ValueOf<T> = T[keyof T];
type UserEventName = ValueOf<typeof USER_EVENT>;
// type UserEventName = "Visit" | "Order"
Upvotes: 10
Reputation: 187272
Just index the type by it's own keys to get a union of the values.
const USER_EVENT = {
pageview: 'Visit',
order: 'Order'
} as const
type UserEventName = typeof USER_EVENT[keyof typeof USER_EVENT] // "Visit" | "Order"
Note the as const
there. This is required to force the type to be inferred as specific strings, and not just string
.
Upvotes: 6