What I'm trying to do is to define some kind of "rich enumeration", where each enum key is linked to some data whose type I want to specify.
E.g., something like this:
const Seasons = {
winter: { temperature: 5, startMonth: "December" },
spring: { temperature: 20, startMonth: "March" },
summer: { temperature: 30, startMonth: "June" },
fall: { temperature: 15, startMonth: "September" },
} as const
This declaration is nice and lets me do things like:
type Season = keyof typeof Seasons // "winter" | "spring" | "summer" | "fall"
and even a type guard like
function isSeason(s: string): s is Season {
return Object.keys(Seasons).includes(s)
}
What I cannot do, though, is get the compiler to check that all “season definitions” have a given type. If I define this:
type SeasonData = typeof Seasons[Season]
then SeasonData
is the union of the type of all definitions—no matter if they have the same shape or not.
So I'm looking for a syntactically non-redundant and light way to define something like:
const Seasons: EnumWith<{temperature: number, startMonth: string}> = ... // as before
^^^^^^^^ <- to be defined!
Especially, I'm trying not to have to repeat the list of seasons in any other structure (interface or array) and to directly infer the type Season
from the object definition (though hearing about alternative is always good!).
What could be done?
I'm not sure I fully understand your use case, the way I'd model the relationship between your types is something like the following
type Season =
| "winter"
| "spring"
| "summer"
| "fall"
type Month =
| "January"
| "February"
| "March"
| "April"
| "May"
| "June"
| "July"
| "August"
| "September"
| "October"
| "November"
| "December"
type SeasonStruct = {
temperature: number
startMonth: Month
}
type Seasons = { [K in Season]: SeasonStruct }
const seasons: Seasons = {
winter: { temperature: 5, startMonth: "December" },
spring: { temperature: 20, startMonth: "March" },
summer: { temperature: 30, startMonth: "June" },
fall: { temperature: 15, startMonth: "September" },
}
This should give you enough building blocks to represent everything you need in your domain, hope it helps.