Setting up a record in typescript using keyof typeof

I’ve set up an object with my enum-like times of das as follows and I’m trying to make the correct type for a record based on these entries.

export const TIMEOFDAY = {
    FirstLight: 'First Light',
    Morning: 'Morning',
    Antemeridiem: 'Antemeridiem',
    Zenith: 'Zenith',
    Postmeridiem: 'Postmeridiem',
    Evening: 'Evening',
    LastLight: 'Last Light',
    Night: 'Night',
}

When I try to set up the record, it tells me that basically all the keys are missing in my record entries. It seems TS can’t see that I’m referencing them via TIMEOFDAY.FirstLight as shown below.

type TimeOfDayData = {
    phase: number
    hours: number
    lux: number
    temperature: number
}

type TimeOfDayDataRecord = Record<keyof typeof TIMEOFDAY, TimeOfDayData>

const TIMEOFDAYDATA: TimeOfDayDataRecord = {
    [TIMEOFDAY.FirstLight]: /*   */ { phase: 1, temperature: 10, hours: 5, lux: 1 },
    [TIMEOFDAY.Morning]: /*      */ { phase: 2, temperature: 23, hours: 8, lux: 100 },
    [TIMEOFDAY.Antemeridiem]: /* */ { phase: 3, temperature: 42, hours: 13, lux: 300 },
    [TIMEOFDAY.Zenith]: /*       */ { phase: 4, temperature: 55, hours: 16, lux: 500 },
    [TIMEOFDAY.Postmeridiem]: /* */ { phase: 3, temperature: 48, hours: 22, lux: 300 },
    [TIMEOFDAY.Evening]: /*      */ { phase: 2, temperature: 32, hours: 25, lux: 100 },
    [TIMEOFDAY.LastLight]: /*    */ { phase: 1, temperature: 15, hours: 30, lux: 1 },
    [TIMEOFDAY.Night]: /*        */ { phase: 0, temperature: -10, hours: 33, lux: 0 },
}

I’m seeing the following error:

Type '{ [x: string]: { phase: number; temperature: number; hours: number; lux: number; }; }' is missing the following properties from type 'TimeOfDayDataRecord': Morning, Antemeridiem, Zenith, Postmeridiem, and 4 more.ts(2740)

Any ideas how to fix this or where I’ve made an error or wrong assumption?

>Solution :

You are almost there. There is a small catch.

type key = keyof typeof TIMEOFDAY;

Here key is a type that accepts keys of TIMEOFDAY. You do not want that. You want the values of all these keys in TIMEOFDAY.

This can be done using bracket notation easily.

type val = typeof TIMEOFDAY[keyof typeof TIMEOFDAY]

The whole could should work as below:

export const TIMEOFDAY = {
    FirstLight: 'First Light',
    Morning: 'Morning',
    Antemeridiem: 'Antemeridiem',
    Zenith: 'Zenith',
    Postmeridiem: 'Postmeridiem',
    Evening: 'Evening',
    LastLight: 'Last Light',
    Night: 'Night',
};

type TimeOfDayData = {
    phase: number
    hours: number
    lux: number
    temperature: number
}

type TimeOfDayDataRecord = Record<typeof TIMEOFDAY[keyof typeof TIMEOFDAY], TimeOfDayData>

const TIMEOFDAYDATA: TimeOfDayDataRecord = {
    [TIMEOFDAY.FirstLight]: /*   */ { phase: 1, temperature: 10, hours: 5, lux: 1 },
    [TIMEOFDAY.Morning]: /*      */ { phase: 2, temperature: 23, hours: 8, lux: 100 },
    [TIMEOFDAY.Antemeridiem]: /* */ { phase: 3, temperature: 42, hours: 13, lux: 300 },
    [TIMEOFDAY.Zenith]: /*       */ { phase: 4, temperature: 55, hours: 16, lux: 500 },
    [TIMEOFDAY.Postmeridiem]: /* */ { phase: 3, temperature: 48, hours: 22, lux: 300 },
    [TIMEOFDAY.Evening]: /*      */ { phase: 2, temperature: 32, hours: 25, lux: 100 },
    [TIMEOFDAY.LastLight]: /*    */ { phase: 1, temperature: 15, hours: 30, lux: 1 },
    [TIMEOFDAY.Night]: /*        */ { phase: 0, temperature: -10, hours: 33, lux: 0 },
}

Link

Leave a Reply