skip to Main Content

I’ve got some types defined as:

export const ABC= {
  A: 'A',
  B: 'B',
  C: 'C',
} as const;

export const DEF = {
  D: 'D',
  E: 'E',
  F: 'F',
} as const;

export type AbcTypes = (typeof ABC)[keyof typeof ABC];
export type DefTypes = (typeof DEF)[keyof typeof DEF];

Now, I’d like to create an object that can have only values present in those types as keys, but it doesn’t need to have them all, so I’m writing the following:

type MyNewDictionary = {
  [pKey in AbcTypes]: {
    [eKey in DefTypes]: {
      onClick: () => void;
      onCancel: () => void;
    }
  }
};
...
const dictionary: MyNewDictionary = {
  [ABC.A]: {
    [DEF.D]: {
      onClick: () => null,
      onCancel: () => null,
    }
  }
};

However, whenever I try to set some of these object keys, it complains because the rest are missing:

Type: { D: { onClick: () => void; onCancel: () => void; } } is missing the following properties from type: ...

I’ve tried using Partial and using keyof, with the same results.

Here you can see a working Typescript playground.

How could I write this so that I can only use keys inside those defined types, but without the obligation to have all the keys used?

2

Answers


  1. Probably mapping modifiers is the thing you’re looking for.

    In your playground, just add two question marks as below:

    type MyNewDictionary = {
      [pKey in AbcTypes]?: {
        [eKey in DefTypes]?: {
          onClick: () => void;
          onCancel: () => void;
        }
      }
    };
    
    Login or Signup to reply.
  2. Partial should have worked, if it didn’t it seems that you’ve used the wrong scope. You need two Partial:

    1. On the highest level to allow not providing all of the AbcTypes
    2. On the next level to allow not providing all of the DefTypes for a specific AbcTypes
    type MyNewDictionary = Partial<{
      [pKey in AbcTypes]: Partial<{
        [eKey in DefTypes]: {
          onClick: () => void;
          onCancel: () => void;
        }
      }>
    }>;
    

    An alternative would be ? mapping modifier.

    type MyNewDictionary = {
      [pKey in AbcTypes]?: {
        [eKey in DefTypes]?: {
          onClick: () => void;
          onCancel: () => void;
        }
      }
    };
    

    You can replace the ? with +? which is what the typescript defaults to when - or + is not provided.

    playground

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