I am trying to work out how to extract a list of keys from an object, while at the same time limiting those keys so they belong to a certain superset of values.
I can either get the list of keys, OR limit the values to an allowed list, but I cannot work out how to do both at the same time.
For example:
// If I don't specify the type of the keys, then I can extract them easily.
const workdayAttributesAuto = {
Monday: 123,
Tuesday: 456,
Floofday: -1, // whoops, I can specify an invalid day though
};
// Now I can extract them to another type just fine. Here only Monday
// and Tuesday are included, but I also get the unwanted invalid value.
export type workdayNamesAuto = keyof typeof workdayAttributesAuto;
// --> type workdayNamesAuto = 'Monday' | 'Tuesday' | 'Floofday';
So to avoid the invalid value, I can specify a type to restrict keys to only a list of allowed values. But in doing so, I can no longer extract the actual keys used, and I end up with all permitted keys instead:
type Days = 'Sunday' | 'Monday' | 'Tuesday'; // only these keys are allowed
const workdayAttributes: Partial<Record<Days, number>> = {
// Sunday is intentionally omitted.
Monday: 123,
Tuesday: 456,
//Floofday: 0, // not allowed to specify invalid days, good
};
// But now the same type includes Sunday, when it wasn't one of the object keys.
export type workdayNames = keyof typeof workdayAttributes;
// --> type workdayNames2 = 'Sunday' | 'Monday' | 'Tuesday';
How can I tell keyof typeof
to only get the keys actually specified in the object, instead of it getting all possible allowed values?
Use the new satisfies operator, new in TS 4.9:
type Days = 'Sunday' | 'Monday' | 'Tuesday'; // only these keys are allowed
const workdayAttributes = {
// Sunday is intentionally omitted.
Monday: 123,
Tuesday: 456,
// Floofday: 0, // not allowed to specify invalid days
} satisfies Partial<Record<Days, number>>;
export type workdayNames = keyof typeof workdayAttributes;
// --> type workdayNames = 'Monday' | 'Tuesday';