skip to Main Content

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?

3

Answers


  1. 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

    Login or Signup to reply.
  2. Ok so based on your comments, you’ll want

    type TimeOfDayDataRecord = Record<keyof typeof TIMEOFDAY, TimeOfDayData>
    

    Where the key for TimeOfDayDataRecord is set to a keyof typeof TIMEOFDAY ("a key from the type expressed from TIMEOFDAY")

    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<keyof typeof TIMEOFDAY, TimeOfDayData>
    
    const TIMEOFDAYDATA: TimeOfDayDataRecord = {
      "FirstLight": /*   */ { phase: 1, temperature: 10, hours: 5, lux: 1 },
      "Morning": /*      */ { phase: 2, temperature: 23, hours: 8, lux: 100 },
      "Antemeridiem": /* */ { phase: 3, temperature: 42, hours: 13, lux: 300 },
      "Zenith": /*       */ { phase: 4, temperature: 55, hours: 16, lux: 500 },
      "Postmeridiem": /* */ { phase: 3, temperature: 48, hours: 22, lux: 300 },
      "Evening": /*      */ { phase: 2, temperature: 32, hours: 25, lux: 100 },
      "LastLight": /*    */ { phase: 1, temperature: 15, hours: 30, lux: 1 },
      "Night": /*        */ { phase: 0, temperature: -10, hours: 33, lux: 0 },
    }
    /*
    
    The type created is:
    type TimeOfDayDataRecord = {
        Morning: TimeOfDayData;
        Antemeridiem: TimeOfDayData;
        Zenith: TimeOfDayData;
        Postmeridiem: TimeOfDayData;
        Evening: TimeOfDayData;
        Night: TimeOfDayData;
        FirstLight: TimeOfDayData;
        LastLight: TimeOfDayData;
    }
    
    And the Object created is:
    {
      "FirstLight": {
        "phase": 1,
        "temperature": 10,
        "hours": 5,
        "lux": 1
      },
      "Morning": {
        "phase": 2,
        "temperature": 23,
        "hours": 8,
        "lux": 100
      },
      "Antemeridiem": {
        "phase": 3,
        "temperature": 42,
        "hours": 13,
        "lux": 300
      },
      "Zenith": {
        "phase": 4,
        "temperature": 55,
        "hours": 16,
        "lux": 500
      },
      "Postmeridiem": {
        "phase": 3,
        "temperature": 48,
        "hours": 22,
        "lux": 300
      },
      "Evening": {
        "phase": 2,
        "temperature": 32,
        "hours": 25,
        "lux": 100
      },
      "LastLight": {
        "phase": 1,
        "temperature": 15,
        "hours": 30,
        "lux": 1
      },
      "Night": {
        "phase": 0,
        "temperature": -10,
        "hours": 33,
        "lux": 0
      }
    }
    */
    

    You also no longer need to use square brackets [] because you no longer need to compute the property.
    Missing any from (or added extra properties not already in) TIMEOFDAY will throw an error for TypeScript too which is handy

    Login or Signup to reply.
  3. You have two problems there, first of all, your keys needs to match string in your enum-like object, so no space in Last light and First Light.

    Second problem is, that typescript inherits type of

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

    like

    const TIMEOFDAY: {
        FirstLight: string;
        Morning: string;
        Antemeridiem: string;
        Zenith: string;
        Postmeridiem: string;
        Evening: string;
        LastLight: string;
        Night: string;
    }
    

    therefore it doesnt match that key type eighter, fir for this is using as const because it makes it readonly.

    type TimeOfDayData = {
        phase: number
        hours: number
        lux: number
        temperature: number
    }
    export const TIMEOFDAY = {
        FirstLight: 'FirstLight',
        Morning: 'Morning',
        Antemeridiem: 'Antemeridiem',
        Zenith: 'Zenith',
        Postmeridiem: 'Postmeridiem',
        Evening: 'Evening',
        LastLight: 'LastLight',
        Night: 'Night',
    } as const
    
    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 },
    }
    

    Working example

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search