ChatGPT解决这个技术问题 Extra ChatGPT

How to define an interface for objects with dynamic keys?

I have an Object like this that is created by underscore's _.groupBy() method.

myObject = {
  "key" : [{Object},{Object2},{Object3}],
  "key2" : [{Object4},{Object5},{Object6}],
  ...
}

How would I define that as an Interface with TypeScript? i don't want to simply define it as myObject:Object = { ... but rather have an own type for it.

Do the different ObjectX have a type or are they just any?

B
Bruno Grieder

Your object looks like a dictionary of Object arrays

interface Dic {
    [key: string]: Object[]
}

The typescript literature often refers to this pattern as "the description of an indexable object" with a general form

interface Dic {
    [key: string|number]: object_type
}

or

type Dic = {
    [key: string|number]: object_type
}

error TS1023: An index signature parameter type must be either 'string' or 'number'.
M
Mikael Couzic

There's now a dedicated Record type in TypeScript:

const myObject: Record<string, object[]> = { ... }

Also, consider typing the keys whenever possible:

type MyKey = 'key1' | 'key2' | ...

const myObject: Record<MyKey, object[]> = { ... }

if exporting can do export type MyType = Record<string, object[]>;
H
Henrique Bruno
{ [x: string]: T }

and

Record<string, T>

usually will serve for all your objectives. However, I got to a strange point where after some type operations the first option was returning to me both [x: string] and [x: number], and I wasn't being able to use the Record, as it was a recursive type operation and Typescript was throwing an error saying my recursive type wasn't generic.

So, studying the really small Record code, I came to this solution that solved my complex problem:

{ [P in string]: T }

Edit: I also usually have this in every Typescript code I write, in a utils.ts file:

export type obj<T = unknown> = Record<string, T>

Faster and cleaner than using the Record all the time.

E.g.:

type MyObjectType = {
  propA: obj; // An object with unknown props
  propB: obj<number>; // An object with number props
}

TS2304: Cannot find name 'T'.
@AlexeySh. the T in the first 3 examples is actually any type you want that your properties should have. E.g. string. You may use any or unknown if they may have any value. In the export type obj<T = unknown> = Record<string, T> example, it is a generic type. T here will have by default the unknown type, but as the last example shows, you may specifically cast it with obj<number>. T will be a number. Feel free to ask for more explanations, I know TS can be somewhat confusing at first. But it is really awesome when you understand its power! :)
A
Asutosh

don't know about interface, for dynamic objects we can go something like this:

let memoTable: { [k: number]: number } = {};
memoTable[1]=5;
memoTable[2]=7;

z
zemil

I would suggest a solution with Map, maybe for someone it will be useful:

type TKey = 'key1' | 'key2' | 'key3';
type TValue = object[];

type TMapper = Map<TKey, TValue>; // But also you can use Record instead of Map

K
Kriti

Instead of using Object as a type use Record

interface myObjInterface {
  [key: string]: Record<string, any>[]
}