Home > Net >  Typescript Record<Key, object> where object "id" property equals Key
Typescript Record<Key, object> where object "id" property equals Key

Time:11-12

I'm trying to make a Record of this shape where the id property equals the key of each object entry:

{
  id_1: {
     id: 'id_1',
     date: 1234
     comment: 'blah'
  },
  id_2: {
     id: 'id_2',
     date: 5678,
     comment: 'boo'
  }
}

Here's what I've come up with so far:

export type TMap<T extends string> = {
  [P in T]: { _id: P; date: number; comment: string };
};

However, when I use it I need to pass in a paremeter like this:

const myMap: TMap<string> = {...}

Is the a simpler way to achieve a record where the key is equal to one of the value's properties?

CodePudding user response:

I'm not sure if it's possible to get the compiler to infer what you want using just an annotation without generics, but you could use a functional approach:

TS Playground link

function validMap <T extends {
  [K in keyof T]: K extends string ? {
    id: K;
    date: number;
    comment: string;
  } : never;
}> (value: T): T {
  return value;
}

const map1 = validMap({
  a: {
    id: 'a',
    date: 1,
    comment: 'hello',
  },
  b: {
    id: 'b',
    date: 2,
    comment: 'world',
  },
});

const map2 = validMap({
  a: {
    id: 'a',
    date: 1,
    comment: 'hello',
  },
  b: {
    id: 'a',
//  ^^
// Type '"a"' is not assignable to type '"b"'.(2322)
    date: 1,
    comment: 'hello',
  },
});

CodePudding user response:

You could specify string as the default type of your TMap:

export type TMap<T extends string = string> = {
  [P in T]: { id: P; date: number; comment: string };
};

Then you could use it like so:

const myMap: TMap = { ... }
  • Related