1

I have a JavaScript object created like this.

const meta = {
  baz: null
}

const response = {
  foo: 1,
  bar: {
    foo: 2,
    buzz: {
      foo: 3,
      ...meta
    },
    ...meta
  },
  ...meta,
  qux: ‘qux’
}

The response object is a plain object that can contain any key. We know the type of keys foo, baz, and qux. We don’t know the other key names but when they do exist, they are objects with a known interface. In fact, the response object is an instance of this interface.

How do I create a TypeScript interface expressing this logic? I want the compiler to allow defining objects like this:

const foo: MyInterface = {
  foo: 1,
  dynamicKey: {
    baz: null
  }
}
lmenus
  • 604
  • 9
  • 27
  • 1
    Would an index signature not work? (think replacing `dynamicKey` with `[key: string]: KnownInterface`) – futur Aug 20 '21 at 03:33
  • 1
    Index signatures might work if you are okay with [this limitation](https://tsplay.dev/wEDgOW). Otherwise I think you want [this question](https://stackoverflow.com/questions/61431397/how-to-define-typescript-type-as-a-dictionary-of-strings-but-with-one-numeric-i) where the answer is translated to be "dictionary of `MyInterface` but with a set of known keys of other types". I can do that when I get to it. – jcalz Aug 20 '21 at 17:31
  • Thanks both @jcalz, the trick was to expand the index signature interface like you showed me in the example. – lmenus Aug 23 '21 at 03:42

1 Answers1

0

Index signatures might work if you are okay with this limitation.

This worked for my use case. The trick was to expand the index signature interface with all values. This has a limitation as was pointed out, but it's a much better situation than not having any type checking or autocompletion. My interface now looks like this.

interface MyInterface extends KnownInterface {
  [key: string]: MyInterface | KnownInterface[keyof KnownInterface];
}
lmenus
  • 604
  • 9
  • 27