My preferences are represented as an enum of strings:
export enum PreferenceTypes {
language = "language",
unit = "unit",
}
To define the structure of an expected object, I can create an interface where the keys correspond to the values of the enum:
export type UnitTypes = "µg/m3" | "ppm" | "ppb";
export type LanguageTypes = "English" | "Spanish";
export interface PreferenceOptions {
[PreferenceTypes.language]: {
name: string;
value: LanguageTypes;
}[];
[PreferenceTypes.unit]: {
name: string;
value: UnitTypes;
}[];
}
Now, my goal is to generate a default preferences object based on user locale. The keys of this new object should be the locale, with each value being an object. Each object's keys should match the PreferenceTypes
, and their values should align with the value
type defined in PreferenceOptions
. However, constructing such a type constraint has proven challenging:
PreferenceByLocale: {
[key: string]: { [key in PreferenceTypes]?: string };
} = {
/** Defaults for UK users */
en: {
language: "English",
unit: "µg/m3",
},
/** Defaults for Spain users */
es: {
language: "Spanish",
unit: "µg/m3",
},
/** Defaults for US users */
us: {
language: "English",
unit: "ppm",
},
};
I am uncertain how to specify that the value of these objects should actually be
{ [T extends key in PreferenceTypes]?: PreferenceOptions[T]['value'] }
without encountering TypeScript errors. It is unclear if what I am attempting is feasible or if my approach to typing is overly complex. Additionally, there should be an error detection mechanism to flag incorrect entries like:
PreferenceByLocale: {
[key: string]: { [key in PreferenceTypes]?: string };
} = {
/** Defaults for mars users */
mrs: {
// This should trigger an error since "Martian" is not included in LanguageTypes
language: "Martian",
unit: "µg/m3",
},
}
Is it possible to achieve such a validation in TypeScript?