Reputation: 9013
I have a dictionary of MessageTemplates
which I'm building up over time and I was hoping that I could then export a type in TypeScript which represents the set of properties hanging off the MessageTemplates
structure but it's objecting.
Feel like I'm doing something silly but I've been looking at this too long not to ask.
Note, I did just figure out that if I use a Class structure -- with static methods hanging off of it -- it does work but I'm still baffled why the plain object literal syntax doesn't work.
Upvotes: 3
Views: 7685
Reputation: 329248
The problem you're having is MessageTemplates
is a value, not a type, and the keyof
index type query operator acts on the name of a type, not a value. One heuristic for telling the difference is to figure out if the name will appear in the compiled JavaScript or not. If it appears at runtime, it's probably a value; if not, it's probably a type. In your case, MessageTemplates
will exist as a variable at runtime, so it's a value.
What you want to apply keyof
to is not MessageTemplates
, but the type of the MessageTemplates
value. And luckily you can use the typeof
type query operator to get the type of a value. So typeof X
for a value named X
returns the type of that value.
(This is not to be confused with the runtime typeof
operator, where typeof X
acts on a value named X
and returns a string like "number"
or "boolean"
at runtime. You can tell which is which from context. If typeof
will appear in the compiled JavaScript, it's the runtime operator. If typeof
is part of a type annotation or declaration and gets erased before compiling to JavaScript, it's the type query operator. I'm sorry; using the same keyword for different things is confusing, but that's the way it is. I guess the language designers prefer to reuse already-reserved keywords so they don't end up breaking existing JavaScript code. Or they think it's fun to make people add all these caveats to their explanations.)
To recap: you don't want keyof MessageTemplates
, but "keyof
the type of MessageTemplates
", which is keyof (typeof MessageTemplates)
. You can remove the parentheses: keyof typeof MessageTemplates
:
export type IMessageTemplateType = keyof typeof MessageTemplates
// type IMessageTemplateType = "upcomingUpload" | ...
Hope that helps. Good luck!
Upvotes: 10