I have a set of preferences, defined as an enum of strings:
export enum PreferenceTypes {
language = "language",
unit = "unit",
}
I can then create an interface to define the shape of an expected object. The keys will be 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 I want to create a default preferences object, based on a user locale. I want the keys of this new object to be the local, and I want the values to be objects. Each object should have keys of type PreferenceTypes
, and the values must be the type of value
that corresponds to that PreferenceType
in PreferenceOptions
. I am trying to construct such a type constraint, but I am having a hard time:
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 dont know how to say that the value of each of these objects should really be { [T extends key in PreferenceTypes]?: PreferenceOptions[T]['value'] }
- that gives me TS errors. I am not sure if what I'm trying to do is possible, or if I'm overthinking my typing. For example, I should be able to get an error if I wrote something like this:
PreferenceByLocale: {
[key: string]: { [key in PreferenceTypes]?: string };
} = {
/** Defaults for mars users */
mrs: {
// I want this to error, as "Martian" does not exist on LanguageTypes
language: "Martian",
unit: "µg/m3",
},
}
Is such a thing possible?
Ok, I think I understand better what you want to do now. I made a revision like this.
export enum PreferenceTypes {
language = "language",
unit = "unit",
}
export type UnitTypes = "µg/m3" | "ppm" | "ppb";
export type LanguageTypes = "English" | "Spanish";
export interface PreferenceOptions {
[PreferenceTypes.language]: LanguageTypes;
[PreferenceTypes.unit]: UnitTypes;
}
export interface PreferenceByLocale {
[key : string]: PreferenceOptions;
}
const PreferenceByLocale: PreferenceByLocale = {
/** 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",
},
mrs: {
language: "Unkown",
unit: "sxsx"
}
};
console.log(PreferenceByLocale);
now it gives the following error for mrs:
I guess that's what you wanted to do. If that's what you want to do and the code is hard to understand, I can explain.