2

I want to make type declaration for the following data structure, in which child structure will reference parent.

In the innermost level, it only has the Struct type, must not hava the Config type anymore.

As level values came from http response during runtime, I can't use it any more.

type levels = "level1" | "level2" | "level3"

I don't know how to make the Config type in the innermost absent.


interface Struct {
  name: string
  i18n: string
}

type  Config = {
  // [level in levels ]: Struct & Config
  [level: string]: Struct & Config
}

const x: Struct & Config = {
  name: "one",
  i18n: "1",
  level1: {
    name: "two",
    i18n: "2",
    level2: {
      name: "three",
      i18n: "3",
      level3: {
        name: "four",
        i18n: "4"
      }
    }
  }
}

Errors in code

Type '{ name: string; i18n: string; }' is not assignable to type 'Struct & Config'. Type '{ name: string; i18n: string; }' is not assignable to type 'Config'. Property 'name' is incompatible with index signature. Type 'string' is not assignable to type 'Struct & Config'. Type 'string' is not assignable to type 'Struct'.

kevin_chen
  • 160
  • 1
  • 1
  • 11
  • What precisely do you mean by "the Config can't be optional"? It is an index signature, so all of its properties are optional (otherwise it would require infinitely many properties). – kaya3 Jan 22 '22 at 14:23
  • Can you give all the "level" attributes the same name, e.g. `next`? – md2perpe Jan 22 '22 at 14:48
  • [This](https://stackoverflow.com/questions/63430129/how-to-mix-index-signature-with-known-properties/63430341#63430341) might give you some idea. – Eldar Jan 22 '22 at 15:00
  • @kaya3 In the innermost level, I don't need the value of the Config interface. – kevin_chen Jan 22 '22 at 15:16
  • But if it "can't be optional" doesn't that mean it is required? Did you mean "must be absent"? – kaya3 Jan 22 '22 at 15:20
  • @md2perpe no, the name "levelX" actual is dynamic, and nested level is uncertain too. – kevin_chen Jan 22 '22 at 15:20
  • @kaya3 Sorry for not confusing . In the innermost level , it only have the Struct type, must not hava the Config type anymore. – kevin_chen Jan 22 '22 at 15:25
  • 1
    Does [this](https://tsplay.dev/w168AN) work for your use cases? If not, please show unsatisfied use cases, preferably as a [mre] with code. Right now the one code example and comment chain aren't quite enough to convey what you're trying to do. – jcalz Jan 22 '22 at 22:21
  • @jcalz updated the post already. – kevin_chen Jan 23 '22 at 15:11
  • That problem happens at every level; you can't have a type which has a string index signature saying every property must be of type `Struct & Config` and then *also* require that `name` and `i18n` be of type `string`; that would require `name` and `i18n` be *both* `string` *and* `Struct & Config`, which is not possible. If you know that the "level" names are going to start with the string `level`, you can use a pattern template literal index signature like [this](https://tsplay.dev/wgXrbN), does that meet your needs? If not, please demonstrate a use case that doesn't work how you want. – jcalz Jan 23 '22 at 20:50
  • Also: [Please replace/supplement images of code/errors with plaintext versions.](https://meta.stackoverflow.com/a/285557/2887218) – jcalz Jan 23 '22 at 20:50
  • I'd turn to mapped type if it is impossible to implement with index type. – kevin_chen Jan 24 '22 at 14:44

0 Answers0